Thursday, March 13, 2014

Fault Contract for Workflow Service

Today I want to share how to define fault contract and throw fault exception from workflow service and how to handle it from the client.

Concept

A little bit of story why should we use fault contract. By default in WCF service, when we throw any exception from the service, WCF automatically know how to handle the exception for you after you have set the <serviceDebug includeExceptionDetailInFaults="true"/> in your service behavior. However, when we want to host the WCF service to the production environment and especially the service is going to be exposed to the public, I am sure you would not like to let people see the exception detail. Therefore, the best practice is to set includeExceptionDetailInFaults="false", and then limit the information expose to the public by using fault contract.

Implementation

I have created another simple leave application sample with workflow. All the code in this article comes from my sample application. You can download the sample code at the very bottom of this article.

First, we need to define the fault object first. This object is used to store the information that you want to share and it is going to be used by the client and send through the network, therefore, make sure it is serializable.

[DataContract]
public class InvalidApplicationDateFault
{
    [DataMember]
    public int ErrorCode { get; set; }

    [DataMember]
    public string Message { get; set; }

    public InvalidApplicationDateFault(int errorCode, string message)
    {
        this.ErrorCode = errorCode;
        this.Message = message;
    }

}

This is my business component code, I am throwing a custom exception. It is optional, it is still okay if you throw an application exception.

public void Apply(Leave leave)
{
    leave.Status = 1; //Apply state
           
    if (leave.StartDate < DateTime.Today)
        throw new InvalidApplicationDateException();

    if (leave.EndDate < leave.StartDate)
        throw new InvalidApplicationDateException();

    var leaveDAC = new LeaveDAC();
    leaveDAC.Create(leave);

}

Then, following is my code activity which call my business component.

public class Apply : CodeActivity
{
    public InArgument<Leave> Leave { get; set; }

    protected override void Execute(CodeActivityContext context)
    {
        Leave leave = context.GetValue(this.Leave);

        LeaveComponent bc = new LeaveComponent();
        bc.Apply(leave);
    }

}

Then, from my workflow, I will try to call my code activity.



In the TryCatch activity, after catching my custom exception, I create my fault object, stuffing the information that I want to share with my client into it. And then, create a new fault exception with fault object type specific (FaultException<InvalidApplicationDateFault>), then assign the fault object into it.

Notice that I have 2 SendReplyToReceive activities? The SendReplyToReceive inside the Catch is sending the fault exception to the client. But, before that, you need to duplicate the SendReplyToReceive activity from the same Receive activity by right clicking the Receive, then select Create SendReply.



Drag the new SendReplyToReceive activity into the catch, then open the Content Definition window. After that, set a parameter with the FaultException type and then assign the fault exception which I had created.



Now, if you have done it correctly, you will see Workflow Service automatically generate a fault contract for you as you can see it in the WSDL.

Note: If you do not see your fault message generated in WSDL, it is because you are not sending FaultException<T> type in SendReplyToReceive activity, and that your client will never be able to catch the correct fault exception.


Testing

Now, I want to test the service whether it is actually throwing the fault exception to my client correctly. This is how my unit test look like:

[TestMethod, ExpectedException(typeof(FaultException<InvalidApplicationDateFault>))]
public void ApplyTest()
{
    LeaveServiceClient proxy = new LeaveServiceClient();

    try
    {
        Leave leave = new Leave();
        leave.Employee = "Tweety Bird";
               
        //Apply leave with past date is not allowed.
        //This would trigger error
        leave.StartDate = new DateTime(2013, 1, 1);
        leave.EndDate = new DateTime(2013, 1, 2);

        leave.Duration = 2;
        leave.DateSubmitted = DateTime.Now;
        leave.CorrelationID = Guid.NewGuid();

        proxy.Apply(leave);
    }
    catch(FaultException<InvalidApplicationDateFault> fex)
    {
        Assert.IsTrue(fex.Detail.ErrorCode == 123);
        throw;
    }
    catch(Exception)
    {
        Debug.WriteLine("Failed to catch FaultException.");
        Assert.Fail();
    }
    finally
    {
        proxy.Close();
    }
}

When the code execution reach the Apply method, the FaultException<InvalidApplicationDateFault> had been thrown from the service and I am able to catch it correctly in my client.

So, when your service is ready to be exposed to public, you can set the following in your service behavior.

<serviceMetadata httpGetEnabled="false"/>
<
serviceDebug includeExceptionDetailInFaults="false"/>

Happy coding!

If you are interested with my source code, feel free to download it from HERE.




Saturday, March 8, 2014

ASP.NET SignalR

Have you ever encounter a system requirement that require you to create a web page that needs to be consistently updated in real time? For example, a stock market watcher. As we know, stock prices are changing from time to time during the trading period. How can we create an efficient web page which able to show the latest price quickly and real time without requiring user to keep clicking a refresh button? I would like to introduce ASP.NET SignalR to solve the problem.

Concept

My stock market watcher has 1 page only. The page allow user to view and update stock prices. Users open the Default.aspx page to view the stock prices. One of the users update the data. The service will trigger the SignalR hub to ask all the clients to refresh their own UI.

So, instead of using polling strategy by having every individual client to refresh their UI in a timely interval. They get triggered to refresh their UI when there is data change and necessary.



So, before the browser can receive the signal from SignalR hub, it needs to be registered with the SignalR hub first. The registration will create a web socket connection between browser and the server. And that, SignalR require a web socket supported browser to best work with such as IE10+. However, it still actually works with older version of browser. check out the list of supported platforms.

Implementation

I will skip some of the basic details like creating ASP.NET web application project and creating the two web pages and UI design, and straight to the point where how to get SignalR works.

First, nuget the SignalR component library or visit the SignalR site to download it manually.


Now, code your web application to start initializing the SignalR hub with the following code:

[assembly: OwinStartup(typeof(StockSample.UI.Web.Hubs.Startup))]
namespace StockSample.UI.Web.Hubs
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var hubConfiguration = new HubConfiguration();
            hubConfiguration.EnableDetailedErrors = true;
            hubConfiguration.EnableJavaScriptProxies = true;

            app.MapSignalR("/signalr", hubConfiguration);
        }
    }

}

In my Default.aspx, I have a grid view and it support edit function. Once I am done designing my UI and ensure the app is functioning, I add the following Javascript references:

<script src="Scripts/jquery-1.6.4.min.js"></script>
<script src="Scripts/jquery.signalR-2.0.2.min.js"></script>
<script src='<%: ResolveClientUrl("~/signalr/hubs") %>'></script>

Then, code the following to let the browser register itself with the hub during page load:

<script type="text/javascript">
    //Get the hub proxy, this is autogenerated during SignalR startup
    var stockHubProxy = $.connection.stockHub;

    //The refresh method is to let server to trigger
    stockHubProxy.client.refresh = function (stock) {

        //Just some tracing purposes
        console.log('Refresh method triggered successfully!');
        console.log(stock);

        //Refresh the gridview with latest data
        $("#stocksGrid tr").each(function (i) {
            if ($(this)[0].id == stock.ID) {
                $(this).find('td:eq(1)').text(stock.Symbol);
                $(this).find('td:eq(2)').text(stock.Company);
                $(this).find('td:eq(3)').text(stock.Last);
                $(this).find('td:eq(4)').text(stock.Min);
                $(this).find('td:eq(5)').text(stock.Max);
                $(this).find('td:eq(6)').text(stock.Change);
                $(this).find('td:eq(7)').text(stock.Volume);

                //highlight the row that has data changed then slowly fade
                $(this).attr('style', 'background-color: yellow;');
                $(this).animate({ backgroundColor: 'white'}, 3000);
            }
        });
    };

    //This event fire when the hub has started
    $.connection.hub.start().done(function () {
        //Just to trace whether your browser successfully connected to SignalR hub
        console.log('Connected to SignalR hub, connection ID = ' + $.connection.hub.id);
    })


</script>

So, notice my stockHubProxy.client.refresh method? This method later will be used in the server code to trigger the Javascript to refresh the data in my grid view. The code below is how I trigger all the clients refresh their UI from server.

//Trigger hub
var context = GlobalHost.ConnectionManager.GetHubContext<StockHub>();

context.Clients.All.refresh(stock);

One awesome thing about SignalR is the stock object that I passed to hub clients with the above C# code. I do not need to manually serialize the C# object into something like JSON or XML, I am able to get the object with value directly and use it in Javascript.

That's it! Amazingly it is easy to use SignalR. In order to verify it is working as expected, I open up 2 browsers, one is IE11 and another is Chrome 33+. I updated one of the value from IE, then the value change immediately in the Chrome.


Summary

Surprisingly SignalR is easy to implement. If you want to have a web page which is able to real time always showing the latest data, what would you do? Web application is always stateless, no way to keep data in memory and display it like a windows form application. I suppose what most people would do is to create a Javascript timer which call a web service in a timely interval to check for any data change. So, which do you think is more efficient? Having a always alive web socket connection or every 3 seconds call a web service with Javascript?

For a quick start, this is the simplest SignalR implementation that I have done with one way from server trigger clients to perform some action. It also support the other way, from client trigger server to execute some methods or logic. You can explore further for more complicated implementation base on the API documents and sample that you can find here.

If you are interested with my complete source code, feel free to download it from here.




Friday, March 7, 2014

VS2013: BrowserLink Cause Javascript or jQuery Perform Very Slowly

Today one of the developers came to me asking for help regarding his web page performance is very bad. His web page contain less than 50 lines of javascript code and using latest version of jQuery. What actually happen is after the page load, it binds a jQuery change event to a dropdown list control, but it takes a few seconds time to complete. We know that by simply clicking the dropdown control, the browser is not responding.

Environment

Project Type: ASP.NET Web Form
IDE Tool: Visual Studio 2013
Browser version: IE11
CPU: i7-3720QM
Memory: 16GB

With the above hardware spec, the browser should not perform badly with a simple javascript. We have tested with IE6 and IE11, we experience the same behavior for both browsers. From the task manager, we realize that the browser process actually spike up the CPU and memory usage for few seconds after the page load.

Profiler

In order to further investigate, I turn on the profiler from my IE11. In case you are not aware of IE actually has a built-in profiler, just press the F12 key, then look for Profiler, click the Play button to start profiling your web page.

Note: Start profiling only when you are ready to load the problematic page. If you start profiling at the starting page, the profiler results are accumulating and you will find too much data and difficult in tracing the actual problem.


So, after loading the problematic web page, I stop the profiler, and to my surprise there are a lot of functions call from a unknown script.


Notice the URL? The browserLink look fishy to me. After some searching, I realize this is a new feature from Visual Studio 2013 which is used to create communication channel between browsers. This article actually recommend you to turn off the BrowserLink before you publish your application.

My developer tested the web page with IE6, his profiler result is slight different from mine, there are a lot of anonymous function call to a URL that contain "poll" keyword. At first thought he may have implemented SignalR in his project that causing the problem, but he is 100% sure no SignalR was developed in his project.

After further explore and understanding how Browser Link work, it actually use SignalR and it explain the result of IE6 profiler show the "poll" keyword because IE6 do not support web socket, SignalR internal change the communication method with polling. Here is the quote from the ASP.NET site article:

"Browser Link uses SignalR to create a communication channel between Visual Studio and the browser. When Browser Link is enabled, Visual Studio acts as a SignalR server that multiple clients (browsers) can connect to. Browser Link also registers an HTTP module with ASP.NET. This module injects special <script> references into every page request from the server."

Solutions

The problem should not happen if you are aware of purpose the debug mode in your config file and you always turn it off while publishing your application to production environment. 

<system.web>
  <compilation debug="true" targetFramework="4.5" />
</system.web>

But, we tested out that turning off debug mode only is not enough, we have to disable the Browser Link from the Visual Studio 2013 before publishing your project, then only you will see the performance improve and no more SignalR stuffs flooding from your profiler.


Alternatively, add the following AppSetting to your config file.

<appSettings>
  <add key="vs:EnableBrowserLink" value="false"/>
</appSettings>



Send Transactional SMS with API

This post cover how to send transactional SMS using the Alibaba Cloud Short Message Service API. Transactional SMS usually come with One Tim...