Quote for the Week

"Learn to enjoy every moment of your life"

Tuesday, October 6, 2015

Asynchronously Vedio streaming using ASP.NET Web API

A lot of people think that ASP.NET Web API is basically a fancy framework for building APIs – which couldn’t be further from the truth. Web API is mainly about the new .NET HTTP programming model it brings to the table – embracing HTTP to perform a whole magnitude of web related tasks; and APIs are just a small portion of that. Hopefully if you follow this blog, you have seen examples of that already, as we often wander in the unkown areas of ASP.NET Web API, beyond building “traditional” APIs.

Today, let’s go back to the HTTP programming model and use Web API to asynchronously stream videos.

More after the jump.

The concept of asynchronous streaming

To perform the async streaming task, we will revert to the class we already previously used on this blog – and that is PushStreamContent. It allows the developer to progressively push packets of data down to the receiving client. Previously, we used PushStreamContent and JavaScript’s Server Sent Events to create an HTML5 chat.

In our new scenario, we will read the video stream from the file on the server’s hard drive, and flush it down to the client (using PushStreamContent) in the packets of 65 536 bytes. The streaming video playback could then start immediately (client doesn’t have to wait for the entire video to be flushed down), without causing unnecessary load on our server, especially as the process of writing to the client happens asynchronously. Once the client disconnects, the writing stops.

Implementation

PushStreamContent takes an Action in its constructor:


public PushStreamContent(Action<Stream, HttpContent, TransportContext> onStreamAvailable);

This Action is called as soon as the output stream (HTTP content to be flushed to the client) becomes available.

Therefore, we could create a small helper class, which would read the from the disk, and expose this activity for PushStreamContent to call repeatedly.

public class VideoStream
{
   private readonly string _filename;

   public VideoStream(string filename, string ext)
   {
      _filename = @"C:UsersFilipDownloads" + filename + "."+ext;
   }

   public async void WriteToStream(Stream outputStream, HttpContent content, TransportContext context)
   {
      try
      {
      var buffer = new byte[65536];

      using (var video = File.Open(_filename, FileMode.Open, FileAccess.Read))
      {
         var length = (int)video.Length;
         var bytesRead = 1;

         while (length > 0 && bytesRead > 0)
         {
            bytesRead = video.Read(buffer, 0, Math.Min(length, buffer.Length));
            await outputStream.WriteAsync(buffer, 0, bytesRead);
            length -= bytesRead;
         }
      }
      }
      catch (HttpException ex)
      {
         return;
      }
      finally
      {
         outputStream.Close();
      }
   }
}

This class is obviously little simplified, for the sake of demo purposes, but hopefully you get the idea. We allow the consumer of the class to give as information about the file (for which we arbitrarily look in a specific location, the Downloads folder in this case). In the WriteToStream method, we proceed to read the file progressively and flush these bits to the output stream.

Notice that the signature of this method matches the Action expected by PushStreamContent and as a result can be used by it.

Now let’s move to the controller action, which, by now, will be very simple (all the heavy lifting happens in the above VideoStream class).


public class VideosController : ApiController
{
   public HttpResponseMessage Get(string filename, string ext)
   {
      var video = new VideoStream(filename, ext);

      var response = Request.CreateResponse();
      response.Content = new PushStreamContent(video.WriteToStream, new MediaTypeHeaderValue("video/"+ext));

      return response;
   }
}

We allow the client to pass video info (name, extension), construct the instance of VideoStream and then create and instance of PushStreamContent which gets returned to the client.

All we need now is just a route registration:

config.Routes.MapHttpRoute(
    name: "DefaultVideo",
    routeTemplate: "api/{controller}/{ext}/{filename}"
);

Consuming the asynchronous video stream

In this case, I will be requesting this video: C:UsersFilipDownloadsCkY96QuiteBitterBeings.webm.

If we run this in the browser that supports WebM, we could see that the video (especially if you open the network inspection console) is streamed rather than loaded at once. To better illustrate this, I have recorded a short video which shows the application in action. I’ve put a breakpoint inside WriteToStream method, to show that subsequent packets of video get sent down *after* the playback has already started; the client can commence the playback already after the first 64kB packet. Also, as soon as the breakpoint hits, nothing more gets sent to the client, yet the browser still continues the playback of what it has already received. 

Summary
While there are arguably many better solution for video streaming (media protocols, media servers and so on), in my opinion, this type of functionality is a pretty nifty example of how flexible Web API can be in terms of working with HTTP programming – and how many different things it can do.

On a side, PushStreamContent itself is a very interesting class, and if used correctly, can be a very powerful weapon in the arsenal of Web API developer. A very interesting article about a similar topic (async with PushStreamContent) can be found here, by Andrés Vettor. Really worth a read!

Thursday, August 13, 2015

LINQ First() vs FirstOrDefault() and Single() vs SingleOrDefault()

LINQ provides element operators which return a single element or a specific element from a collection. The elements operators are Single, SingleOrDefault, First, FirstOrDefault, Last, LastOrDefault.

Single

It returns a single specific element from a collection of elements if element match found. An exception is thrown, if none or more than one match found for that element in the collection.

SingleOrDefault

It returns a single specific element from a collection of elements if element match found. An exception is thrown, if more than one match found for that element in the collection. A default value is returned, if no match is found for that element in the collection.
List<int> data = new List<int> { 10, 20, 30, 40, 50 };

//Try to get element at specified position
Console.WriteLine(data.ElementAt(1)); //result:20 

//Try to get element at specified position if exist, else returns default value
Console.WriteLine(data.ElementAtOrDefault(10)); //result:0, since default value is 0 

Console.WriteLine(data.First()); //result:10 
Console.WriteLine(data.Last()); //result:50

//try to get first element from matching elements collection
Console.WriteLine(data.First(d => d <= 20)); //result:10 

//try to get first element from matching elements collection else returns default value
Console.WriteLine(data.SingleOrDefault(d => d >= 100)); //result:0, since default value is 0 

//Try to get single element 
// data.Single(); //Exception:Sequence contains more than one element 

//Try to get single element if exist otherwise returns default value
// data.SingleOrDefault(); //Exception:Sequence contains more than one element 

//try to get single element 10 if exist
Console.WriteLine(data.Single(d => d == 10)); //result:10 

//try to get single element 100 if exist otherwise returns default value
Console.WriteLine(data.SingleOrDefault(d => d == 100)); //result:0, since default value is 0

First

- It returns first specific element from a collection of elements if one or more than one match found for that element. An exception is thrown, if no match is found for that element in the collection.

FirstOrDefault

  • It returns first specific element from a collection of elements if one or more than one match found for that element. A default value is returned, if no match is found for that element in the collection.

When to use Single, SingleOrDefault, First and FirstOrDefault ?

  • You should take care of following points while choosing Single, SingleOrDefault, First and FirstOrDefault:
  • When you want an exception to be thrown if the result set contains many records, use Single or SingleOrDefault.
  • When you want a default value is returned if the result set contains no record, use SingleOrDefault.
  • When you always want one record no matter what the result set contains, use First or FirstOrDefault.
  • When you want a default value if the result set contains no record, use FirstOrDefault.

Perfomance of SingleOrDefault and FirstOrDefault

  • FirstOrDefault usually perform faster as compared SingleOrDefault, since these iterate the collection until they find the first match. While SingleOrDefault iterate the whole collection to find one single match.

Friday, July 24, 2015

Microsoft IE8 browser support ending in 17 months

Microsoft is ending support for Internet Explorer 8, announcing it would give users 17 months to stop using the version, which is the most popular version so far.

The post from Microsoft includes a list of operating systems and browser version combinations that would continue getting support, with Internet Explorer 8 not making the cut.

"After Jan. 12, 2016, only the most recent version of Internet Explorer available for a supported operating system will receive technical support and security updates," said Roger Capriotti, director of Internet Explorer, in the full blog post. "For example, customers using Internet Explorer 8, Internet Explorer 9, or Internet Explorer 10 on Windows 7 SP1 should migrate to Internet Explorer 11 to continue receiving security updates and technical support."

Microsoft



The news is especially big for businesses, many of which have not upgraded their systems to Windows 7 or 8 because it means that they would also have to upgrade Internet Explorer.

The post says Microsoft would only be supporting IE9 on Windows Vista, IE10 on Windows Server 2012 and IE11 on Windows 7 and Windows 8.1.

While the browsers will stop getting updates and technical support from Microsoft, they will continue to work on the systems they're installed on.

"Running a modern browser is more important than ever for the fastest, most secure experience on the latest Web sites and services," Capriotti continued in his blog post.

The news takes Microsoft in a different direction from its previous support policy, in which it promised to continue supporting a version of IE as long as an operating system was able to run it.

Under the old policy, IE7 was to continue getting support until 2017, which is when Windows Vista support was to end. IE8 would have continued to get support until 2020, when Windows 7 was to retire. IE10 was supposed to continue getting support until 2023, the end date for Windows 8.

Microsoft has essentially taken off a year of support for IE7, four years for IE8 and IE9 and seven years for IE10.

This news is especially surprising considering the user base and the rate of growth of IE8. The browser is being used by 37 percent of Internet Explorer users, which is a lot more than IE11's 29 percent. Not only that, but in the last month alone IE8 use has grown four times that of IE11.

While at first glance it may seem like Microsoft is losing its mind, the company suggests users will have a better web experience with new versions of Internet Explorer. Not only that, but the move will obviously also help cut Microsoft's support costs. 

LikeFollowShare(167)Tweet(47)Reddit9 Comments