SilverReader – ultra fast Google Reader alternative

One of the side projects I’ve been working on for last three months is SilverReader – ultra fast RSS reader. My colleges and me have worked very hard to deliver you adequate Google reader successor.

Today I want to announce that SilverReader is finally available for public.

Speed and performance

We have fine tuned our product to deliver customers best speed and performance. Today with current number of users http://www.silverreader.com/ we are :
about 2x faster than Google reader ,
about 5x faster than Feedly web version ,
about 5x faster than AOL.Reader  and
about 8x faster than Digg reader .

We do realize that these products above have larger number of users so their servers are more loaded.
However we will also scale our servers with increasing number of users. This way we will try to stay with current performance numbers and deliver customers performance they deserve.

User interface

We have created clean and simple user interface. Here is a screenshot of main UI :

MainPage

Easy transition from Google reader or other RSS readers

We have implemented one click migration from Google Reader.
When you login with Google account you can with one click import your subscriptions and folders from Google Reader. We do not support migration of bookmarks and tags.

We also have option of import/export via OPML file. Migration usually finishes in less then a sec for 10K subscriptions.

Security

Security is very important to us. Unlike some of our competitors we do support secure connection (HTTPS) on login and optionally trough entire application (if someone want to receive all articles encrypted) .

Technologies we used

We created SilverReader as SPA – Single Page Web Application. This way we can give customers some advanced features that aren’t available in traditional web applications.
SilverReader has been created with following mayor tools / frameworks:
Database : Microsoft SQL Server 2012
Backend :  ASP.NET Web API, ASP.NET MVC
Frontend : Knockout.js, Durandal, JQuery, HTML5

Help and support

We strongly believe in customer feedback . You can vote and suggest any feature using our suggestion page . We also have a rich help content you can read on this location .
In next few months we will constantly improve our product. We want to give you some great new features but without affecting simplicity of UI.

Our business model

Our business model is rather simple. We will always have a free version you can use (will be always fully functional for reading feeds). Later we will add premium account option which will offer some more advanced features to more demanding users.

Phone and Tablet usage

In v1 SilverReader does not support responsive design (design optimized for smaller devices) .
Our user interface is very complicated so we haven’t got time to optimize it for smaller devices.
We also haven’t got time to create Android, IOS and WP applications.

As you can see when you login into SilverReader we are committed to deliver our customers high quality products.

We are aware how smaller devices are important and we will work hard in next two months to deliver you high quality Android, IOS and WP applications.

What’s next ?

This is beginning of series of articles where I will reveal you how we have build this excellent product.
I will cover ASP.NET Web API part as well as SPA part of our application.
Stay tuned for more news.

Request throttling in ASP.NET Web API

Real world scenario

When you start to build real world REST API you will surely try to limit access to you API. You can limit number of concurrent requests by using http://www.iis.net/download/dynamiciprestrictions
or some other tools.

In this post I will try to limit access to my ASP.NET Web API by using my own code building my own custom DelegatingHandler.

What you will see here

In this code bellow is ThrottleRateHandler that will be used to limit number of calls to your API in hour. Also these same code will limit how many times you can call API in seconds.

These class is using code similar as StackOverflow has used for their throttle rate handler.
Also these code is based on Token authorization approach.

I will also use HTTPRuntime.Cache to implement this functionality. I plan for my real world REST API to use MemBase caching. So question for my readers: Is it smart to replace HTTPRuntime.Cache with MemBase later ?

Here is code for ThrottleRateHandler :

public class ThrottleRateHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            string query = request.RequestUri.Query;
            string accessToken = HttpUtility.ParseQueryString(query).Get("accessToken");
            double seconds = Convert.ToDouble(WebConfigurationManager.AppSettings["throttleTimeoutForMethodCall"]);
            int numberRequests = Convert.ToInt32(WebConfigurationManager.AppSettings["tokenRequestsPerHour"]);

            if (accessToken != null)
            {
                var throttleKey = string.Format(
                    "{0}-{1}", request.RequestUri.AbsolutePath, accessToken);
                var tokenKey = accessToken;
                var allowExecute = false;

                if (HttpRuntime.Cache[throttleKey] == null)
                {
                    // this check was added for integration testing
                    if (!seconds.Equals(0.0))
                    {
                        HttpRuntime.Cache.Add(
                            throttleKey,
                            true,
                            null,
                            DateTime.Now.AddSeconds(seconds),
                            Cache.NoSlidingExpiration,
                            CacheItemPriority.Low,
                            null);
                    }

                    allowExecute = true;
                }

                if (allowExecute)
                {
                    var hit = (HitInfo)(HttpRuntime.Cache[tokenKey] jQuery152020203585348297026_1330795835814 new HitInfo());

                    if (hit.Hits > numberRequests)
                    {
                        allowExecute = false;
                    }
                    else
                    {
                        hit.Hits++;
                    }

                    if (hit.Hits == 1)
                    {
                        HttpRuntime.Cache.Add(
                            tokenKey,
                            hit,
                            null,
                            DateTime.Now.AddMinutes(60),
                            Cache.NoSlidingExpiration,
                            CacheItemPriority.AboveNormal,
                            null);
                    }

                    if (!allowExecute)
                    {
                        return this.ReturnException(string.Format("You can call API {0} times per hour", numberRequests));
                    }
                }
                else
                {
                   return this.ReturnException(string.Format("You can call API every {0} seconds", seconds));
                }
            }
            else
            {
                var response = new HttpResponseMessage
                {
                    Content =
                        new StringContent("You must supply valid token to access method!"),
                    StatusCode = HttpStatusCode.Unauthorized
                };
                return Task<HttpResponseMessage>.Factory.StartNew(() => response);
            }

            return base.SendAsync(request, cancellationToken);
        }

        private Task<HttpResponseMessage> ReturnException(string message)
        {
            var response = new HttpResponseMessage
            {
                Content = new StringContent(message),
                StatusCode = HttpStatusCode.Conflict
            };
            return Task<HttpResponseMessage>.Factory.StartNew(() => response);
        }

        public class HitInfo
        {
            public HitInfo()
            {
                Hits = 1;
            }

            public string Token { get; set; }
            public int Hits { get; set; }
        }
    }

ASP.NET Web API Authorization using Tokens

Planning real world REST API

When you try to plan how to build real world REST API like other major players like Facebook or Foursquare have you will soon realize that all major players use OAuth 2.0 .

ASP.NET Web API comes with support for authorize attribute and that’s nice, but for real world API I want to support token based approach.

OAuth 2.0 Server

For supporting token based approach  you must have some kind of server that will issue tokens. Building token server can be complex and most major players have implemented OAuth 2.0 server based on draft 10 OAuth documentation.
We hope that Microsoft will provide us with their own OAuth 2.0 server for free in final version of ASP.NET MVC 4.
Meanwhile I will just assume that you already have your own OAuth 2.0 server.

Building ActionFilterAttribute

I have solved my problem with authorization by implementing RequireAuthorize ActionFilterAttribute. This attribute also have scope property. Scope property is used for limiting access to your REST API.

You just need to decorate controllers or actions in controllers with this attribute and optionally set required scope for accessing these actions.
Here is RequireAuthorizeAtribute:

public class RequireAuthorization : ActionFilterAttribute
    {
        public string Scope { get; set; }

        public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            string[] scope = null;
            if (!string.IsNullOrEmpty(Scope))
            {
                scope = Scope.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            }

            string query = actionContext.Request.RequestUri.Query;
            string accessToken = HttpUtility.ParseQueryString(query).Get("accessToken");

            // we first check for valid token
            if (accessToken != null)
            {
                IAccessTokenValidator accessTokenValidator = new AccessTokenValidator();
                bool validToken = accessTokenValidator.ValidateToken(accessToken, scope);

                if (!validToken)
                {
                    var response = new HttpResponseMessage
                    {
                        Content =
                            new StringContent("This token is not valid, please refresh token or obtain valid token!"),
                        StatusCode = HttpStatusCode.Unauthorized
                    };
                    throw new HttpResponseException(response);
                }
            }
            else
            {
                var response = new HttpResponseMessage
                {
                    Content =
                        new StringContent("You must supply valid token to access method!"),
                    StatusCode = HttpStatusCode.Unauthorized
                };
                throw new HttpResponseException(response);
            }

            base.OnActionExecuting(actionContext);
        }
    }

And here is AccessTokenValidator class:

public class AccessTokenValidator : IAccessTokenValidator
    {
        public bool ValidateToken(string token, string[] scope)
        {
            // replace this logic with dataBase access to table with tokens
            if (token != "someToken")
            {
                return false;
            }
            return true;
        }
    }

Force JSON DelegatingHandler for ASP.NET Web API

 Building real world REST API-s

When you decide to build real world REST API-s like Facebook or Foursquare and many others have you must think on lot of things such as security, scoping, throttling and similar.

One of the first thing you will encounter is need to support various media formats such as JSON, XML, PNG … in easy way.

ASP.NET Web API support JSON and XML formats out of the box and provide us with easy way to support any custom mediaType format.

I will try to provide you with series of posts in which I will try to explain how I have created real world REST API using ASP.NET Web API.

Common ways to enforce custom format

There are several ways to enforce custom format in REST API :
1) You can pass mediaType in request header .
2) You can pass mediaType in URI using following syntax : http://api.mySite.com/v1/contacts/1/JSON

3) You can pass mediaType in URI using following syntax : http://api.mySite.com/v1/contacts/1.JSON

4) You can pass mediaType in URI using following syntax : http://api.mySite.com/v1/contacts/1?mediaType=JSON

My preferred solution using ASP.NET Web API

First approach – I will support
In REST API you will sure want to support first approach in which user passes mediaType in request header.

Second approach – I will not support
For second approach things are little difficult .

To support this way you will probably need to change routes like this where you pass optional parameter ext for mediaType extension :

config.Routes.MapHttpRoute(
                "Default", 
                "{controller}/{id}/{ext}", 
                new { id = RouteParameter.Optional, ext = RouteParameter.Optional } 
            );

Problem with this approach is that your code will only work for URI like this where you try to get particular contact with id 1 in JSON format:
http://api.mySite.com/v1/contacts/1/JSON
When you try to get all contacts in JSON format using URI like this it will fail:
http://api.mySite.com/v1/contacts/JSON

Instead of trying to get all contacts in that format in will try to find contact which has id with value “JSON” .

One possible way to resolve this is to have two controllers for same model. One called ContactController another ContactsController.

I just don’t prefer this solution. If you know any other solution to resolve this feel free to comment. You can read more about this in this sites :

http://codebetter.com/glennblock/2012/02/28/why-are-there-2-controllers-in-the-asp-net-web-api-contactmanager-example-rest-has-nothing-to-with-it-2/

http://wekeroad.com/2012/02/28/someone-save-us-from-rest/

Third approach – I will not support

You may be wondering why it is so nice and clean? I don’t like dots in URI in that way. You cannot parse that QueryString safely to get that extensions behind dot.

You can try do something like this :

requestString.EndsWith(".JSON")

But then you will get another wall. In this version of ASP.NET Web API when you try to change Request.RequestUriinside DelegatingHandlers method SendAsync and pass changed RequestUri to base, ASP.NET Web API still try to goto old RequestUri. It seams like routing is performed before DelegatingHandler…So if we try to get mediaType in DelegatingHandler from RequestUri :

http://api.mySite.com/v1/contacts/1.JSON

then substring URI to become:

http://api.mySite.com/v1/contacts/1

and pass new RequestUri to base we will not be successful.

Fourth approach – I will support

I have choose to support fourth approach. For using this approach you will need to add this line of code in GlobalAsax.cs :

config.MessageHandlers.Add(new UriFormatExtensionMessageHandler());

Here is my code for UriFormatExtensionMessageHandler :

public class UriFormatExtensionMessageHandler : DelegatingHandler
   {    
       private bool shouldForceJson;
       private bool sholudForceXml;
       public void CheckFormats(HttpRequestMessage request)
       {
           // uri must contain mediaType parameter to enforce that media type
           string query = request.RequestUri.Query;
           string mediaType = HttpUtility.ParseQueryString(query).Get("mediaType");
           if (mediaType != null)
           {
               switch (mediaType)
               {
                   case "JSON":
                       shouldForceJson = true;
                       break;
                   case "XML":
                       sholudForceXml = true;
                       break;
               }
           }
       }

protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, 
System.Threading.CancellationToken cancellationToken)
       {
           CheckFormats(request);
           if (shouldForceJson)
           {
               // clear the accept and replace it to use JSON.
               request.Headers.Accept.Clear();
               request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
               shouldForceJson = false;
           }

           if (sholudForceXml)
           {
               request.Headers.Accept.Clear();
               request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
               sholudForceXml = false;
           }

           return base.SendAsync(request, cancellationToken);
       }
   }

UPDATE :

For fourth approach Microsoft has provided solution in this version of WebApi.You should you code bellow :

config.Formatters.JsonFormatter.MediaTypeMappings.Add(
              new QueryStringMapping("mediaType", "json", "application/json"));

            config.Formatters.XmlFormatter.MediaTypeMappings.Add(
               new QueryStringMapping("mediaType", "xml", "application/xml"));


    

  

Blog Redesign

Blog design revamped

I have decided after long period of not blogging to start over again and best thing you can do for fresh start is to redesign your blog. My choice this time is light background instead of dark background. It seams at least for me that is easier to read and focus on content on light backgrounds. This is tiny screenshot how my old blog looked like :

blog

I have also tried to incorporate minimalistic approach but I don’t know if I have succeeded.
Because I am not designer I have hired designer to do all work for me. You will be able to contact him soon if you want by link in bottom of page “Designed by…” that I will insert in few days.

Migrate old content to new design

I have decided to not migrate old blog content to new design. What I am mean by migrate is to change “Syntax highlighting” for code, reposition pictures, content and insert missing H1,H2 headers for some posts and similar.
Because this is fresh start I want to start fresh and not go back to old content.

My writing focus

My old readers probably are aware that my focus was Silverlight and .NET development. I will continue to have focus on Silverlight because Silverlight probably will remain best technology for development intranet browser applications for long time.

I will also have strong focus on Kinect, Azure, Windows Phone and Win 8 development.

I have worked on some projects that involve these technologies and I will try to write about things I have learned on this blog.

Your comments?

What do you think about my new blog design and choice of my writing focus ?

WPF Validation using Validation Application Block Part 2 – Client side

This is second part of my article where I talk about Validation in WPF using Entlib Validation Application Block. First part of my article is located on this location : http://blog.developers.ba/post/2009/07/07/WPF-Validation-using-Validation-Application-Block-41-Part-1-e28093-Server-side/

There are many articles about client side validation in WPF. Most of these articles are similar and use implementation of IDataErrorInfo interface on Model class.

I have use some methods  already described in other articles just to show you how easy it is to implement client side validation in WPF using VAB.

I have model class called Customer where I have implemented IDataErrorInfo. Code looks like this :

public string Error
{
get {
StringBuilder error = new StringBuilder();
ValidationResults results = Validation.ValidateFromAttributes<Customer>(this);
foreach (ValidationResult result in results)
{
error.AppendLine(result.Message);
}
return error.ToString() ;
}
}
public string this[string columnName]
{
get {
ValidationResults results = Validation.ValidateFromAttributes<Customer>(this);
foreach (ValidationResult result in results)
{
if (result.Key == columnName)
{
return result.Message;
}
}
return string.Empty;
}
}

I have called ValidateFromAttributes method of Validation class that exists in VAB to get collection of ValidationResults. It is easy as that.

In Application.Resources of my WPF application I have defined some textbox error template and style to use when validation error is occurred. For this I have borrowed some code from other articles to save on time writing templates and styles.

And final in xaml on textboxes I have added following code where I have turn on Validation and defined witch error template to use :

<TextBox x:Name="txtFirstName"  Grid.Column="1"  TextWrapping="Wrap" 
Text="{Binding FirstName, ValidatesOnDataErrors=True}" Validation.ErrorTemplate="{StaticResource TextBoxErrorTemplate}" />

References :

http://msdn.microsoft.com/en-us/magazine/cc700358.aspx

http://www.eggheadcafe.com/tutorials/aspnet/f726cd7d-cfcc-43c3-85d8-2afc75e7a08a/wpf-input-validation-with.aspx

1 2 3