[Dev Tip] CORS on REST WCF

Yesterday I encountered the following question in the MSDN forums about calling a cross-domain WCF RESTful service from Chrome.

The problem with doing the above is because there is a cross-domain call to a WCF service. When you are using Chrome, the browser tries to find out if it can do the call by sending a cross-origin resource sharing (CORS) request, as explained in this article. In IE, you will most likely get a cross-domain exception.

After searching the web a bit, I found that the immediate solution is to change the supported HTTP method of the operation to “*”, and to add the special cross-origin headers to the outputted response, like so:

WebOperationContext.Current.OutgoingResponse.Headers.Add(
  “Access-Control-Allow-Origin”, “*”); WebOperationContext.Current.OutgoingResponse.Headers.Add(
  “Access-Control-Allow-Methods”, “POST”); WebOperationContext.Current.OutgoingResponse.Headers.Add(
  “Access-Control-Allow-Headers”, “Content-Type, Accept”);

There are two problems with this solution:

  1. You need to repeat these lines in each of your service methods.
  2. The service method is called twice, once for the “preflight” request (the request with the OPTIONS HTTP verb), and a second time for the invocation itself.

So I took the time and written a special endpoint behavior that can be attached to any webHttpBinding based endpoint.

The code does the following:

1. Every response message gets the “Access-Control-Allow-Origin” header with the value of “*”, to tell the client that the service allowed the request from the client.

2. If the client sends a request to the service with the verb OPTIONS (this is referred to as a “preflight” request), the service will automatically return a 200 (ok) response with the required headers: “Access-Control-Allow-Headers” and “Access-Control-Allow-Methods” (in addition to the allow-origin header). Clients that look for the “allow” headers in the response will then send the original required request to the service.

The benefits of using this behavior is:

  1. The code that returns the message with the headers is located in the behavior itself – no need to place it in each service method.
  2. The behavior catches the OPTIONS request, and does not require running the service method twice.
  3. You do not need to change any part of your service contract or service implementation. The behavior is only needed to be applied using configuration.

To implement this behavior I used a message inspector that checks the request and changes the response, and an operation invoker that wraps the unhandled operation invoker. The custom operation invoker handles the OPTIONS message requests, which otherwise would have caused the service to return an error message (because no method is set to handle “Options” requests).

The endpoint behavior can be attached to the endpoint through configuration, like so:

<behaviors>

<endpointBehaviors>

<behavior name=”webSupport”>

<webHttp />

<CorsSupport />

</behavior>

</endpointBehaviors>

</behaviors>

<extensions>

<behaviorExtensions>

<add name=”CorsSupport” type=”WebHttpCors.CorsSupportBehaviorElement, WebHttpCors, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null” />

</behaviorExtensions>

</extensions>

<services>

<service name=”Service.JSonService”>

<endpoint address=”http://localhost:8080″ behaviorConfiguration=”webSupport” binding=”webHttpBinding” contract=”Service.IJSonService” />

</service>

</services>

Or, if you are using IIS to host your services, I also created a service host factory that creates a WebServiceHost and adds the behavior to every webHttpBinding based endpoint created by the host. To use it in your .svc file, just write something like this:

<%@ ServiceHost Language=”C#” Debug=”true” Service=”Service.JSonService, Service”Factory=”WebHttpCors.CorsWebServiceHostFactory, WebHttpCors” %>

You can download the behavior code + two sample hosts (IIS and self-hosted) that shows how to use the behavior from my skydrive.

To test the two hosts, open the webform1.aspx and change the target URL to access the IIS/self-hosted service.

Enjoy.

REF: http://blogs.microsoft.co.il/idof/2011/07/02/cross-origin-resource-sharing-cors-and-wcf/

With js:

IE was ok with it. Firefox was not ok with it.

Then you gotta remember that handle their .Send() requests differently (inside JQUERY).

It all makes sense now.

//JavaScript snipplet

if (window.XMLHttpRequest) {

    returnObject = new XMLHttpRequest();

} else if (window.ActiveXObject) {

    returnObject = new ActiveXObject("Microsoft.XMLHTTP");

} else {

msg = "Your browser doesn't support AJAX!";

}

Here are some key words, phrases that I’ve been googling/binging that finally led me somewhere.

    Result: [Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIXMLHttpRequest.statusText]" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)" location: "JS frame :: http://localhost:53692/test/WCFCallTestViaJQ14.htm :: HandleJQueryError :: line 326" data: no]


XMLHttpRequest Send "NS_ERROR_FAILURE"

JQuery Ajax WCF Self Hosted CORS JSON

Ref: http://stackoverflow.com/questions/7234599/cors-support-within-wcf-rest-services

Source Code: https://mega.co.nz/#!NppCwJ4D!S6sUVFYU-_qpK7Flml-i0QMod8V9Qq7vyWbkek8KVp4

[Dev Tip] REFACTORING THE ASP.NET MVC APPLICATION TO THE ONION ARCHITECTURE

Source Code on GitHub

Background

Any application should be fairly tested before it shipped to the customer. Biggest challenge in the testing is tightly coupled behavior of the UI with the Application Logic and further to the Database logic .Good testable systems are the one in which presentation layer does not directly depends on the application logic and the database logic. Application logic should be independent of UI such that both can be tested independent of each other. For example you should not call DBContext methods on click event of a button from the UI. If you do so, then the UI is tightly coupled with the database layer and any change in the database logic will impact the UI. Other disadvantage is that to unit test the database logic you need the UI. Testing of various components of the application is as important as building the components of the application. You should able to do the Unit Testing without the need of the database. Now let us assume, you are creating an ASP.NET MVC application and you have written all the database codes (fetching records or inserting etc.) in the controller itself. Your application may be up and running but in this pattern, you cannot unit test the controller without database. Other problem could be, you may have duplicate the database codes in different controllers and certainly you would not like that. There are challenges with duplicate codes. One change in database logic may require you to do multiple changes in the code. Other problem is your controller is aware of the underlying database source and if in future you change the data source, the controller will be affected and again this is not the best practice to create an ASP.NET MVC application. These problems are not only restricted to MVC but can exist in any kind of applications which is having database logic tightly coupled with the application itself.

Let us summarize problems we discussed above:

  • Duplicate database access codes
  • Hard to maintain the codes
  • Difficulties in Unit Testing
  • Hard to replace type of data sources
  • Tough to put centralized database access related policy

Usual approach we follow is the Layered Architecture. In layered architecture the presentation layer is transitively depends on the database layer and that does not solve the problem we discussed earlier in an absolute way.

Onion Architecture is the preferred way of architecting application for better testability, maintainability and dependability on the infrastructures like databases and services. This term was first coined by Jeffery Palermo in his blog back in 2008.

Learn more about the Onion Architecture in the series of blog posts by Jeffery Palermo

  • In the Onion Architecture layers talk to each other using the Interfaces. Any concrete implantation would be provided to application at the run time.
  • Any external dependency like database access and the web service call are part of the external layers
  • UI is part of the external layers
  • Objects representing domain are part of the internal layers or they are the centers
  • External layers can depend on the layers internal to it or central to it
  • Internal layer should not depend on the external layers.
  • Domain object which is at the core or center can have access to the both the UI and the database layers.
  • All the coupling are towards the center
  • Codes which may change often should be part of the external layers

I would recommend you to watch Steve Smith course on same topic at Pluralsight for better understanding on the concepts of the Onion Architecture. I will not go much into discussion of Onion architecture and jump into showing you refactoring ASP.NET MVC application to use the Onion Architecture.

Create N-Tier application using C# by Steve Smith

Setup

Let us implement Repository Pattern in MvcMovieRTM ASP.NET MVC Application. You can download this app from official Microsoft site here . After downloading, open the app in Visual Studio and in Package Manager Console run the command update-database. Go ahead and press F5 to run the application. Navigate to Movie Controller and you should able to see list of movies, can edit, delete and create new movie. We are going to refactor this application to adhere the Repository Pattern. Before we move ahead, let us examine the code in MoviesController.

image

As you see in the above code snippet that inside the controller we are directly accessing the database. All logics to fetch data from database is written right inside the controller and that makes the controller and the database access tightly coupled to each other. You cannot unit test Index action in isolation of database.

Refactoring to Repository Pattern

Follow the following steps to refactor the existing application:

Create two class library projects and give them name as MvcMovie.Infrastructure andMvcMovie.Core. In the project MvcMovie.Infrastructure all database related operation will be placed. In this example Entity Framework is used. So all Entity Framework dependency will be part of MvcMovie.Infrastructure project.

Setting up Infrastructure Project

Let’s start with moving the MovieDBContext class to the MvcMovie.Infrastructure project. Infrastructure project will contain all the database related classes and the operations. Since application is using Entity framework, we need to add the Entity framework reference in Infrastructure project. From Nuget manager add Entity framework package in the project. MovieDBContext class will look like as follows:

MovieDBContext.cs

1
2
3
4
5
6
7
8
9
10
11
using System.Data.Entity;
namespace MvcMovie.Infrastructure
{
    public class MovieDBContext : DbContext
    {
        public DbSet<Movie> Movies { get; set; }
    }
}

Next create MovieRepository class in the Infrastructure project. This class will contain all the database operations. Essentially we will move operations which are directly working with MovieDbContext class from the MoviesController to MovieRepository class. After moving the Entity framework codes the MovieRepository class will look like follows:

MovieRepository.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
using MvcMovie.Core;
using System;
using System.Collections.Generic;
using System.Data.Entity;
namespace MvcMovie.Infrastructure
{
    public class MovieRepository : IMovieRepository, IDisposable
    {
        MovieDBContext db = new MovieDBContext();
        public IEnumerable<Movie> GetMovies()
        {
            
                return db.Movies;
            
        }
        public void Add(Movie m)
        {
          
                db.Movies.Add(m);
                db.SaveChanges();
           
        }
        public void Edit(Movie m)
        {
            
                db.Entry(m).State = EntityState.Modified;
                db.SaveChanges();
            
        }
        public void Remove(int id)
        {
                Movie movie = db.Movies.Find(id);
                db.Movies.Remove(movie);
                db.SaveChanges();
            
        }
        public void Dispose()
        {
            db.Dispose();
        }
    }
}

Once MovieRepository class is created refactor it to extract Interface from this class. You need to move extracted interface to the MvcMovie.Infrastructure project.

clip_image002

Visual Studio will extract the IMovieRepository interface and put it inside the MvcMovie.Infrastructure project. Move the IMovieRepository interface to the MvcMovie.Core project. IMovieRepository will look like follows in MvcMovie.Core project:

IMovieRepository.cs

1
2
3
4
5
6
7
8
9
10
11
12
using System;
using System.Collections.Generic;
namespace MvcMovie.Core
{
   public interface IMovieRepository
    {
        void Add(Movie m);
        void Edit(Movie m);
        IEnumerable<Movie> GetMovies();
        void Remove(int id);
    }
}

Do not forget to implement the IMovieRepository interface in the MovieRepository class. At this point of time if you go ahead and build the MvcMovie.Infrastructure project, you will get compile time errors. In solution explorer MvcMovie.Infrastructure project should look like follows:

clip_image002[6]

Setting up Core Project

Move Movie class from the MvcMovie project to the MvcMovie.Core project. To work with data annotations add reference of System.ComponentModel.DataAnnotaions in the MvcMovie.Core project. Movie class should look like follows in core project:

Movie.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System;
using System.ComponentModel.DataAnnotations;
namespace MvcMovie.Core
{
  public class Movie
    {
        public int ID { get; set; }
        [StringLength(60, MinimumLength = 3)]
        public string Title { get; set; }
        [Display(Name = "Release Date")]
        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        public DateTime ReleaseDate { get; set; }
        [RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]
        [Required]
        [StringLength(30)]
        public string Genre { get; set; }
        [Range(1, 100)]
        [DataType(DataType.Currency)]
        public decimal Price { get; set; }
        [RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]
        [StringLength(5)]
        public string Rating { get; set; }
    }
}

You should have the IMovieRepository interface and the Movie class inside the MvcMovie.core project. In solution explorer the MvcMovie.Core project will look as follows:

clip_image002[8]

Compile MvcMovie.Core project and add its reference to the MvcMovie and the MvcMovie.Infrastruture project. After adding reference of the MvcMovie.Core in the MvcMovie.Infrastructure project, you should able to successfully compile the MvcMovie.Infrastructure project.

Refactor MoviesController

Previously in the MoviesController class we were directly creating instance of the MovieDBContext and performing database operations. To follow Onion Architecture, controller will only know about the IMovieRepository and perform database operations using the IMovieRepository. Very first let’s create instance of the IMovieRepository

1
private IMovieRepository db = new MovieRepository() ;

Next any database operation will be performed on instance of MovieRepository. Some of the operations are as follows:

Fetch Genre

1
2
3
var GenreQry = from d in db.GetMovies()
               orderby d.Genre
               select d.Genre;

Fetch All Movies

1
2
var movies = from m in db.GetMovies()
                         select m;

Add Movie

1
db.Add(movie);

Edit Movie

1
db.Edit(movie);

Remove Movie

1
db.Remove(movie.ID);

Replace various database operations in MoviesController with the code as shown above. As of now you should successfully able to run the application.

Inverting the Dependency

We are directly creating instance of the MovieRepository in the MoviesController which makes Controller tough for Unit Test. In this scenario to test the Controller, you need the database. We can solve this problem by inverting the control using any DI Container. You are free to use any DI container of your choice, however I am using Microsoft provided Unity Container. To use it add the Unity reference using Nuget Package Manger. In Unity.Config (located in the App_Start) folder register the type as given below:

1
container.RegisterType<IMovieRepository, MovieRepository>();

Once type is registered you need to call the RegisterComponents() method of UnityConfig in the Application_Start() method of the Global.asax.cs as shown below:

1
UnityConfig.RegisterComponents();

As the last step refactor Controller as shown below:

clip_image002[10]

If you remember in beginning we were directly creating the instance of the MovieDBcontext inside controller hence the controller was fully dependent on database and was making it tough to test it in isolation.

MvcMovie application has been refactored to Onion Architecture. Next task you may want to do, is to download the code discussed in this post from GitHub and start writing test.

Source Code on GitHub

Summary

We have refactored the application adhering to the onion architecture. Domain objects like Movie is at the center of the architecture and are the part of internal layers. The Infrastructure project in which we are working with database and database logics are part of the external layers. They depend on the centeral layers like core. UI or in this case the MVC application is also an external layer and depndes on the Core project. All layers are interacting to each other using the interfaces rather than the concrete definitions. You can very easily write Unit Test against the controllers using Fake or Mock without hitting the datbase. In future you can easily change data access technology from Enity Framework to something else without affecting the UI and the Core.

Resources

Source Code on GitHub

Learn more about the Onion Architecture in the series of blog posts by Jeffery Palermo

REF: http://debugmode.net/2014/09/12/refactoring-the-asp-net-mvc-application-to-the-onion-architecture/

[Dev Tip] Decouple OWIN Authorization Server from Resource Server

Recently I’ve received lot of comments and emails asking how we can decouple the OWIN Authorization Server we’ve built in the previous posts from the resources we are protecting. If you are following the posts mentioned below you will notice that we’ve only one software component (API) which plays both roles: Authorization Server and Resource Server.

There is nothing wrong with the the current implementation because OAuth 2.0 specifications never forces the separation between the Authorization Server and the Resource Server, but in many cases and especially if you have huge resources and huge number of endpoints you want to secure; then it is better from architecture stand point to decouple the servers. So you will end up having a stand alone Authorization Server, and another stand alone Resource Server which contains all protected resources, as well this Resource Server will understand only the access tokens issued from the Authorization Server.

You can check the source code on Github.

OAuth 2.0 Roles: Authorization Server, Resource Server, Client, and Resource Owner

Before we jump into implementation and how we can decouple the servers I would like to emphasis onOAuth 2.0 roles defined in the specifications; so we’ll have better understanding of the responsibility of each role, by looking at the image below you will notice that there are 4 roles involved:

OAuth 2.0 Roles

Resource Owner:

The entity or person (user) that owns the protected Resource.

Resource Server:

The server which hosts the protected resources, this server should be able to accept the access tokens issued by the Authorization Server and respond with the protected resource if the the access token is valid.

Client Applications:

The application or the (software) requesting access to the protected resources on the Resource Server, this client (on some OAuth flows) can request access token on behalf of the Resource Owner.

Authorization Server:

The server which is responsible for managing authorizations and issuing access tokens to the clients after validating the Resource Owner identity.

Note: In our architecture we can have single Authorization Server which is responsible to issue access token which can be consumed by multiple Resource Servers.

Decoupling OAuth 2.0 OWIN Authorization Server from Resource Server

In the previous posts we’ve built the Authorization Server and the Resource Server using a single software component (API), this API can be accessed on (http://ngauthenticationAPI.azurewebsites.net), in this demo I will guide you on how to create new standalone Resource API and host it on different machine other than the Authorization Server machine, then configure the Resource API to accept only access tokens issued from our Authorization Server. This new Resource Server is hosted on Azure can be accessed on (http://ngauthenticationResourcesAPI.azurewebsites.net).

Note: As you noticed from the previous posts we’ve built a protected resource (OrdersController) which can be accessed by issuing HTTP GET to the end point(http://ngauthenticationAPI.azurewebsites.net/api/orders), this end point is considered as a resource and should be moved to the Resource Server we’ll build now, but for the sake of keeping all the posts on this series functioning correctly; I’ll keep this end point in our Authorization Server, so please consider the API we’ve built previously as our standalone Authorization Server even it has a protected resource in it.

Steps to build the Resource Server

In the steps below, we’ll build another Web API which will contain our protected resources, for the sake of keeping it simple, I’ll add only one secured end point named “ProtectedController”, any authorized request to this end point should contain valid bearer token issued from our Authorization Server, so let’s start implementing this:

Step 1: Creating the Resource Web API Project

We need to add new ASP.NET Web application named “AngularJSAuthentication.ResourceServer” to our existing solution named “AngularJSAuthentication”, the selected template for the new project will be “Empty” template with no core dependencies, check the image below:

Resourse Server New Project

Step 2: Install the needed NuGet Packages

This project is empty so we need to install the NuGet packages needed to setup our OWIN Resource Server, configure ASP.NET Web API to be hosted within an OWIN server, and configure it to only uses OAuth 2.0 bearer tokens as authorization middle ware; so open NuGet Package Manager Console and install the below packages:

The usage for each package has been covered on the previews posts, feel free to check this post to know the rational of using each package is used for.

Step 3: Add OWIN “Startup” Class

Now we want to add new class named “Startup”. It will contain the code below:

As we’ve covered in previous posts, this class will be fired once our Resource Server starts, as you noticed I’ve enabled CORS so this resource server can accept XHR requests coming from any origin.

What worth noting here is the implementation for method “ConfigureOAuth”, inside this method we are configuring the Resource Server to accept (consume only) tokens with bearer scheme, if you forget this one; then your Resource Server won’t understand the bearer tokens sent to it.

Step 3: Add “WebApiConfig” Class

As usual we need to add the WebApiConfig class under folder “App_Start” which contains the code below:

This class is responsible to enable routing attributes on our controller.

Step 4: Add new protected (secured) controller

Now we want to add a controller which will serve as our protected resource, this controller will return list of claims for the authorized user, those claims for sure are encoded within the access token we’ve obtained from the Authorization Server. So add new controller named “ProtectedController” under “Controllers” folder and paste the code below:

Notice how we attribute the controller with [Authorize] attribute which will protect this resource and only will allow HTTP GET requests containing a valid bearer access token sent in the authorization header to pass, in more details when the request is received the OAuth bearer authentication middle ware will perform the following:

  1. Extracting the access token which is sent in the “Authorization header” with the “Bearer” scheme.
  2. Extracting the authentication ticket from access token, this ticket will contain claims identity and any additional authentication properties.
  3. Checking the validity period of the authentication ticket.

Step 5: Hosting the Authorization Server and Resource Server on different machines

Until this step and if you are developing locally on your dev machine, if you tried to obtain an access token from your Authorization Server i.e. (http://AuthServer/token) and then send this access token to the secured end point in our Resource Server i.e. (http://ResServer/api/protected) the result for this request will pass and you will have access to the protected resource, how is this happening?

One your dev machine once you request an access token from your Authorization Server; the OAuth middleware will use the default data protection provider in your Authorization Server, so it will use the “validationKey” value in machineKey node stored in machine.config file to issue the access token and protect it. The same case applies when you send the access token to your Resource Server, it will use the same machineKey to decrypt the access token and extract the authentication ticket from it.

The same applies if you are planing on your production environment to host your Authorization Server and your Resource Server on the same machine.

But in our case I’m hosting my Authorization Server on Azure website using West-US region, and my Resource Server is hosted on Azure websites on East-US region so both are totally on different machines and they share different machine.config files. For sure I can’t change anything on machine.config file because it is used by different sites on the Azure VMs I’m hosting my APIs on it.

So to solve this case we need to override the machineKey node for both APIs (Authorization Server and Resource Server) and share the same machineKey between both web.config files.

To do so we need to generate a new machineKey using this online tool, the result after using the tool will be as the below: As advised by Barry Dorrans it is not recommend to use an online tool to generate your machineKey because you do not know if this online tool will store the value for your machineKey in some secret database, it is better to generate the machineKey by your self.

To do so I’ll follow the steps mentioned in article KB 2915218, Appendix A which uses Power Shell commands to generate machineKey, so after you open Power Shell and run the right command as the image below you will receive new machineKey
PowerShell MachineKey

Note: Do not use those for production and generate a new machineKey for your Servers using Power Shell.

After you generate it open the web.config file for both the Authorization Server (AngularJSAuthentication.API project) and for the Resource Server (AngularJSAuthentication.ResourceServer) and paste the machineKey node inside the <system.web> node as the below:

By doing this we’ve unified the machineKey for both Authorization Server and Resource Server (Only this API in case of Azure shared hosting or any other shared host) and we are ready now to test our implementation.

Step 6: Testing the Authorization Server and Resource Server

Now we need to obtain an access token from our Authorization Server as we did before in the previous posts, so we can issue HTTP POST to the end point (http://ngauthenticationapi.azurewebsites.net/token) including the resource owner username and password as the image below:

Obtain Access Token

If the request succeeded we’ll receive an access token, then we’ll use this access token to send HTTP GET request to our new Resource Server using the protected end point (http://ngauthenticationresourcesapi.azurewebsites.net/api/protected), for sure we need to send the access token in the Authorization header using bearer scheme, the request will be as the image below:

Consume Access Token

As you notice we’re now able to access the protected resource in our new Resource Server and the claims for this identity which obtained from the Authorization Server are extracted.

That’s it for now folks, hopefully this short walk through helped in understanding how we can decouple the Authorization Server from the Resource Server.

If you have any comment or question please drop me a comment

You can use the following link to check the demo application.

You can use the following link to test the Authorization Server (http://ngauthenticationAPI.azurewebsites.net),

You can use the following link to test the Resource Server (http://ngauthenticationResourcesAPI.azurewebsites.net) 

You can check the source code on Github.

REF: http://bitoftech.net/2014/09/24/decouple-owin-authorization-server-resource-server-oauth-2-0-web-api/

[Dev Tip] The Onion Architecture

Part 1 – begin:

I’ve spoken several times about a specific type of architecture I call “Onion Architecture”.  I’ve found that it leads to more maintainable applications since it emphasizes separation of concerns throughout the system.  I must set the context for the use of this architecture before proceeding.  This architecture is not appropriate for small websites.  It is appropriate for long-lived business applications as well as applications with complex behavior.  It emphasizes the use of interfaces for behavior contracts, and it forces the externalization of infrastructure.  The diagram you see here is a representation of traditional layered architecture.   This is the basic architecture I see most frequently used.  Each subsequent layer depends on the layers beneath it, and then every layer normally will depend on some common infrastructure and utility services.  The big drawback to this top-down layered architecture is the coupling that it creates.  Each layer is coupled to the layers below it, and each layer is often coupled to various infrastructure concerns.  However, without coupling, our systems wouldn’t do anything useful, but this architecture creates unnecessary coupling.

The biggest offender (and most common) is the coupling of UI and business logic to data access.  Yes, UI is coupled to data access with this approach.  Transitive dependencies are still dependencies.  The UI can’t function if business logic isn’t there.  Business logic can’t function if data access isn’t there.  I’m intentionally ignoring infrastructure here because this typically varies from system to system.  Data access changes frequently.  Historically, the industry has modified data access techniques at least every three years; therefore, we can count on needing to modify data access three years from now for any healthy, long-lived systems that’s mission-critical to the business.  We often don’t keep systems up-to-date because it’s impossible to do.  If coupling prevents easily upgrading parts of the system, then the business has no choice but to let the system fall behind into a state of disrepair.  This is how legacy systems become stale, and eventually they are rewritten.

I propose a new approach to architecture.  Honestly, it’s not completely new, but I’m proposing it as a named, architectural pattern.  Patterns are useful because it gives software professionals a common vocabulary with which to communicate.  There are a lot of aspects to the Onion Architecture, and if we have a common term to describe this approach, we can communicate more effectively.

The diagram to the left depicts the Onion Architecture.  The main premise is that it controls coupling.  The fundamental rule is that all code can depend on layers more central, but code cannot depend on layers further out from the core.  In other words, all coupling is toward the center.   This architecture is unashamedly biased toward object-oriented programming, and it puts objects before all others.

In the very center we see the Domain Model, which represents the state and behavior combination that models truth for the organization.  Around the Domain Model are other layers with more behavior.  The number of layers in the application core will vary, but remember that the Domain Model is the very center, and since all coupling is toward the center, the Domain Model is only coupled to itself.  The first layer around the Domain Model is typically where we would find interfaces that provide object saving and retrieving behavior, called repository interfaces.  The object saving behavior is not in the application core, however, because it typically involves a database.  Only the interface is in the application core.  Out on the edges we see UI, Infrastructure, and Tests.  The outer layer is reserved for things that change often.  These things should be intentionally isolated from the application core.  Out on the edge, we would find a class that implements a repository interface.  This class is coupled to a particular method of data access, and that is why it resides outside the application core.  This class implements the repository interface and is thereby coupled to it.

The Onion Architecture relies heavily on the Dependency Inversion principle.  The application core needs implementation of core interfaces, and if those implementing classes reside at the edges of the application, we need some mechanism for injecting that code at runtime so the application can do something useful.

The database is not the center.  It is external.   Externalizing the database can be quite a change for some people used to thinking about applications as “database applications”.  With Onion Architecture, there are no database applications.  There are applications that might use a database as a storage service but only though some external infrastructure code that implements an interface which makes sense to the application core.  Decoupling the application from the database, file system, etc, lowers the cost of maintenance for the life of the application.

Alistair Cockburn has written a bit about Hexagonal architecture.  Hexagonal architecture and Onion Architecture share the following premise:  Externalize infrastructure and write adapter code so that the infrastructure does not become tightly coupled.

I’ll be writing more about the Onion Architecture as a default approach for building enterprise applications.  I will stay in the enterprise system space and all discussion will reside in that context.  This gets even more interesting when there are multiple processes making up a single software system.

Part 1 – end

Part 2 – begin:

In part 1, I introduced an architectural pattern that I have named “Onion Architecture”.  The object-oriented design concepts are not new, but I’m pulling together a lot of techniques and conventions into a single pattern and giving it a name.  My hope is that the industry can use this name to communicate the architectural approach where appropriate.

Part 2:  Practical example:

CodeCampServer uses the Onion Architecture.  If you are looking for a full, working application as an example, please have a look.  The practical example I put before you is taken directly from CodeCampServer.  It is a narrow, vertical slice of an example.  I’m keeping the scope small as to be digestible.  I’ll start with a diagram so you can understand where all the code resides within the layers of the onion.

CodeCampServer uses the ASP.NET MVC Framework, so SpeakerController is part of the user interface.  This controller is coupled to the ASP.NET MVC Framework, and there is no getting around that.  SpeakerController depends on IConferenceRepository and IUserSession (and IClock, but we’ll omit that).  The controller only depends on interfaces, which are defined in the application core.  Remember that all dependencies are toward the center.

Turn your attention to the ConferenceRepository and UserSession classes.  Notice that they are in layers outside of the application core, and they depend on the interfaces as well, so that they can implement them.  These two classes each implement an interface closer to the center than itself.  At runtime, our Inversion of Controlcontainer will look at its registry and construct the proper classes to satisfy the constructor dependencies of SpeakerController, which is the following:

public SpeakerController(IConferenceRepository conferenceRepository,
                         IUserSession userSession, IClock clock)
    : base(userSession)
{
    _conferenceRepository = conferenceRepository;
    _clock = clock;
    _userSession = userSession;
}

At runtime, the IoC container will resolve the classes that implement interfaces and pass them into the SpeakerController constructor.  At this point in time, the SpeakerController can do its job.

Based on the rules of the Onion Architecture, the SpeakerController _could_ use UserSession directly since it’s in the same layer, but it cannot use ConferenceRepository directly.  It must rely on something external passing in an instance of IConferenceRepository.  This pattern is used throughout, and the IoC container makes this process seamless.

At the end of this series, I plan on publishing a full working system that adheres to the Onion Architecture pattern.  The systems we build for clients use this approach, but I’m not at liberty to discuss that code, so I will craft a reference application for those of you who prefer a concrete Visual Studio solution to digest.

Part 2 – end

Part 3 – begin:

In my previous installments, I described what has become my approach to defining the architecture for an application.  Based on feedback, I’ve modified my diagrams a bit to reduce ambiguity and emphasize key points.  The goal of part 3 of this series is to compare and contrast the Onion Architecture with traditional layered architecture.  I will flatten the Onion Architecture to see what it looks like compared to traditional layered architecture, and I will force the layered architecture into an onion.  Whereas the shape can be either, the structure of the actual application is radically different from what is commonly known and accepted.  I’ll define four tenets of Onion Architecture at the end.

I must stress again:  I am not claiming any breakthroughs in technology or technique.  I have learned from other industry thought leaders like Martin Fowler, Ward Cunningham, Kent Beck, Michael Feathers and others (especially those I’ve had the privilege to work with here in Austin, TX).  I’m putting forth the Onion Architecture as an architectural pattern by which we can communicate this radically different architectural approach.  Not “radically different as in new”.  Different as in not mainstream.

Let’s review.  Traditional layered architecture can look somewhat like the diagram depicted on the right.  Each layer communicates with the layer below it.  The UI talks to business logic, but it does not talk directly to data access, WCF, etc.  The layering approach does call out the need to keep certain categories of code out of the UI.  The big downfall is that business logic ends up coupled to infrastructure concerns.  Data Access, I/O, and Web Services are all infrastructure.  Infrastructure is any code that is a commodity and does not give your application a competitive advantage.  This code is most likely to change frequently as the application goes through years of maintenance.  Web services are still fairly new, and the first version in .Net, ASMX, is already deprecated in favor of WCF.  We can be assured that WCF’s days are numbered as well, so it is foolish to tightly couple the business logic to WCF.  Data access changes every two years or so, so we definitely don’t want to be tightly coupled to it.  For long-life, we would want our business logic to be independent of these infrastructure concerns so that as infrastructure changes, the business logic doesn’t have to.

Let’s review Onion Architecture.  The object model is in the center with supporting business logic around it.  The direction of coupling is toward the center.  The big difference is that any outer layer can directly call any inner layer.   With traditionally layered architecture, a layer can only call the layer directly beneath it.  This is one of the key points that makes Onion Architecture different from traditional layered architecture.  Infrastructure is pushed out to the edges where no business logic code couples to it.  The code that interacts with the database will implement interfaces in the application core.  The application core is coupled to those interfaces but not the actual data access code.  In this way, we can change code in any outer layer without affecting the application core.  We include tests because any long-lived application needs tests.  Tests sit at the outskirts because the application core doesn’t couple to them, but the tests are coupled to the application core.  We could also have another layer of tests around the entire outside when we test the UI and infrastructure code.

This approach to application architecture ensures that the application core doesn’t have to change as:  the UI changes, data access changes, web service and messaging infrastructure changes, I/O techniques change.

To the right, I have created a diagram which attempts to show what Onion Architecture would look like when represented as a traditionally layered architecture.  The big difference is that Data Access is a top layeralong with UI, I/O, etc.  Another key difference is that the layers above can use any layer beneath them, not just the layer immediately beneath.  Also, business logic is coupled to the object model but not to infrastructure.

To the left here I have attempted to represent traditionally layered architecture using concentric circles.  I have used black lines around the layers to denote that each outer layer only talks to the layer immediately toward the center.  The big kicker here is that we clearly see the application is built around data access and other infrastructure.  Because the application has this coupling, when data access, web services, etc. change, the business logic layer will have to change.  The world view difference is how to handle infrastructure.  Traditional layered architecture couples directly to it.  Onion Architecture pushes it off to the side and defines abstractions (interfaces) to depend on.  Then the infrastructure code also depends on these abstractions (interfaces).  Depending on abstractions is an old principle, but the Onion Architecture puts that concepts right up front.

Key tenets of Onion Architecture:

  • The application is built around an independent object model
  • Inner layers define interfaces.  Outer layers implement interfaces
  • Direction of coupling is toward the center
  • All application core code can be compiled and run separate from infrastructure

I encourage you to use the term “Onion Architecture” when speaking about architectures that adhere to the above four tenets.  I believe that this approach to architecture leads to long-lived systems that are easy to maintain.  Also, in my experience, this architecture yields dividends soon after a project starts since it makes the code a breeze to change.

Although I don’t call out an IoC container as a key tenet, when using a mainstream language like Java or C#, an IoC container makes the code fit together very easily.  Some languages have IoC features built-in, so this is not always necessary.  If you are using C#, I highly recommend using Castle Windsor or StructureMap.

Part 3 – end

Part 4 – begin:

In 2008, I coined a new pattern name called Onion Architecture.  You can read the previous parts here: part 1part 2part 3.  Over these four years, I’ve spoken about this pattern at user groups, conferences, and it’s even published in one of the chapters of ASP.NET MVC in Action from Manning.

I’ve been overwhelmed by the traction this pattern name has enjoyed.  Folks from all over the country have written about and have talked about the pattern.  Some of the ones I’ve noticed are here (please comment with more – I welcome it).

Back in 2008, I defined four tenets of Onion Architecture:

  • The application is built around an independent object model
  • Inner layers define interfaces.  Outer layers implement interfaces
  • Direction of coupling is toward the center
  • All application core code can be compiled and run separate from infrastructure

Although there has been significant adoption of this pattern, I have received countless questions about how to implement it in various environments.  I mostly get asked about how it relates to domain-driven design.  First, onion architecture works well with and without DDD patterns.  It works well with CQRS, forms over data, and DDD.  It is merely an architectural pattern where the core object model is represented in a way that does not accept dependencies on less stable code.

CodeCampServer was an original sample of onion architecture, but it also grew as a sample of how to do ASP.NET MVC in various ways, how to use Portable Areas, and how to use MvcContrib features like input builders.  If you are just looking for onion architecture, it has too much going on.  I have pushed a much simpler solution that represents onion architecture concepts.  I have intentionally not included a UI input form or an IoC container, which most people associate with onion architecture.  Onion architecture works just fine without the likes of StructureMap or Castle Windsor.  Please check out the code here and let me know if this presents a simple approach – that is the goal.

When there is enough interest, I will continue this series with more parts.  CQRS definitely deserves some addressing within this architecture, and so do object models that support task-based UIs.

Get the code here at my BitBucket repository.

Part 4 – end

Ref: http://jeffreypalermo.com/blog/the-onion-architecture-part-1/

Source code: https://mega.co.nz/#!5ppTVJIY!x4pDBusK15psNmaMcgm3pemq6gah0KlwX4tKBKN_gr0

[Dev tip] Difference between WCF and Web API and WCF REST and Web Service

Web Service

  1. It is based on SOAP and return data in XML form.
  2. It support only HTTP protocol.
  3. It is not open source but can be consumed by any client that understands xml.
  4. It can be hosted only on IIS.

WCF

  1. It is also based on SOAP and return data in XML form.
  2. It is the evolution of the web service(ASMX) and support various protocols like TCP, HTTP, HTTPS, Named Pipes, MSMQ.
  3. The main issue with WCF is, its tedious and extensive configuration.
  4. It is not open source but can be consumed by any client that understands xml.
  5. It can be hosted with in the applicaion or on IIS or using window service.

WCF Rest

  1. To use WCF as WCF Rest service you have to enable webHttpBindings.
  2. It support HTTP GET and POST verbs by [WebGet] and [WebInvoke] attributes respectively.
  3. To enable other HTTP verbs you have to do some configuration in IIS to accept request of that particular verb on .svc files
  4. Passing data through parameters using a WebGet needs configuration. The UriTemplate must be specified
  5. It support XML, JSON and ATOM data format.

Web API

  1. This is the new framework for building HTTP services with easy and simple way.
  2. Web API is open source an ideal platform for building REST-ful services over the .NET Framework.
  3. Unlike WCF Rest service, it use the full featues of HTTP (like URIs, request/response headers, caching, versioning, various content formats)
  4. It also supports the MVC features such as routing, controllers, action results, filter, model binders, IOC container or dependency injection, unit testing that makes it more simple and robust.
  5. It can be hosted with in the application or on IIS.
  6. It is light weight architecture and good for devices which have limited bandwidth like smart phones.
  7. Responses are formatted by Web API’s MediaTypeFormatter into JSON, XML or whatever format you want to add as a MediaTypeFormatter.

To whom choose between WCF or WEB API

  1. Choose WCF when you want to create a service that should support special scenarios such as one way messaging, message queues, duplex communication etc.
  2. Choose WCF when you want to create a service that can use fast transport channels when available, such as TCP, Named Pipes, or maybe even UDP (in WCF 4.5), and you also want to support HTTP when all other transport channels are unavailable.
  3. Choose Web API when you want to create a resource-oriented services over HTTP that can use the full features of HTTP (like URIs, request/response headers, caching, versioning, various content formats).
  4. Choose Web API when you want to expose your service to a broad range of clients including browsers, mobiles, iphone and tablets.

[Life] Useful tools

http://www.hanselman.com/blog/ScottHanselmans2014UltimateDeveloperAndPowerUsersToolListForWindows.aspx

Script to take ownership of folder (add to context menu):


Windows Registry Editor Version 5.00

;Adds Take Ownership command to the context menu in Vista
;Also provides "Administrators" group with Full Control permissions.

[-HKEY_CLASSES_ROOT\*\shell\runas]

[HKEY_CLASSES_ROOT\*\shell\runas]
@="Take Ownership"
"Extended"=""
"NoWorkingDirectory"=""

[HKEY_CLASSES_ROOT\*\shell\runas\command]
@="cmd.exe /c takeown /f \"%1\" && icacls \"%1\" /grant administrators:F"

[-HKEY_CLASSES_ROOT\Directory\shell\runas]

[HKEY_CLASSES_ROOT\Directory\shell\runas]
@="Take Ownership"
"Extended"=""
"NoWorkingDirectory"=""

[HKEY_CLASSES_ROOT\Directory\shell\runas\command]
@="cmd.exe /c takeown /f \"%1\" /r /d y && icacls \"%1\" /grant administrators:F /t"

[Infographic] 15 mẹo nhỏ chống mệt mỏi sau chuyến bay dài

header - lam sao de han che trieu chung met moi sau mot chuyen bay dai.

Hiện nay du lịch đã trở thành một ngành kinh tế mũi nhọn của hầu hết các quốc gia trên thế giới. Du lịch không chỉ đem lại lợi ích về kinh tế mà còn là cơ hội quảng bá truyền thống văn hoá của mỗi quốc gia.Du lịch phát triển kéo theo sự gia tăng của nhiều dịch vụ kèm theo như nhà hàng, khách sạn,…và giao thông đặc biệt là đường hàng không.

Di chuyển bằng máy bay đem lại nhiều sự tiện lợi cho du khách, tuy nhiên có một vấn đề mà hầu hết ai cũng gặp phải là sựmệt mỏi sau những chuyến bay đường dài. Mệt mỏi kéo dài do cơ thể không kịp thích nghi với sự thay đổi múi giờ gây ra ảnh hưởng không nhỏ đến việc tận hưởng kỳ nghỉ của mỗi du khách. Infographic dưới đây sẽ giới thiệu vài điều cơ bản cần lưu ý về triệu chứng mệt mỏi này và những mẹo nhỏ giúp hạn chế tác động của nó lên cơ thể.

[Submit] lam sao de han che trieu chung met moi sau mot chuyen bay dai.

Nguồn: graphs.net

[Dev tip] Converting SOAP-based WCF Service to RESTful Design

Introduction

When SOAP is believed to be overkill, some developers may choose RESTful services. REST (Representative State Transfer) is mostly used when developers need high range of interoperability and when trying to restrict themselves to basic XML messages or JSON that are transmitted over HTTP. RESTful services are fundamentally different from SOAP-based services because they don’t attempt to achieve transport neutrality. In fact, RESTful services typically embrace HTTP as the only transport used throughout the system. Using REST, developers can model their services as resources and give these resources unique identifiers in the form of URIs. In this article, we will take an existing SOAP-based service and convert it over to a more RESTful design.

Background

The Existing WCF SOAP Based Service

SOAP is developed on a great deal of work that’s been happening throughout the industry to implement a completely new protocol stack for services. It means that additional features or capabilities that we want to implement for our services should be possible to implement in a transport neutral way. And we’ll accomplish that in this protocol stack by using an XML-based messaging layer. Now, this is where SOAP comes into the picture. SOAP is a particular XML vocabulary for packaging up messages that we need to transmit to our services. The following is the code for the WCF based service before it’s converted to a RESTful service. The backend is using Entity Framework utilizing the Northwind database. Then it’s followed by an image, which is the sample result of the GetAllProducts, showing the SOAP request and response.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
using System.ServiceModel;

namespace SoapToRESTfullDemo
{
    [ServiceContract]
    public interface IProductService
    {
        [OperationContract]
        List<ProductEntity> GetAllProducts();
        [OperationContract]
        ProductEntity GetProductByID(int productID);
        [OperationContract]
        bool UpdateProduct(ProductEntity product);
    }

    [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
    public class ProductService : IProductService
    {
        #region IProductService Members
        public List<ProductEntity> GetAllProducts()
        {
            List<ProductEntity> products = new List<ProductEntity>();
            ProductEntity productEnt = null;
            using (var NWEntities = new NorthwindEntities())
            {
                List<Product> prods = (from p in NWEntities.Products
                                 select p).ToList();
                if (prods != null)
                {
                    foreach (Product p in prods)
                    {
                        productEnt = new ProductEntity()
                        {
                            ProductID = p.ProductID,
                            ProductName = p.ProductName,
                            QuantityPerUnit = p.QuantityPerUnit,
                            UnitPrice = (decimal)p.UnitPrice,
                            UnitsInStock = (int)p.UnitsInStock,
                            ReorderLevel = (int)p.ReorderLevel,
                            UnitsOnOrder = (int)p.UnitsOnOrder,
                            Discontinued = p.Discontinued
                        };
                        products.Add(productEnt);
                    }
                }
            }
            return products;
        }

        public ProductEntity GetProductByID(int productID)
        {
                ProductEntity productEnt = null;
                using (var NWEntities = new NorthwindEntities())
                {
                    Product prod = (from p in NWEntities.Products
                                       where p.ProductID == productID
                                       select p).FirstOrDefault();
                    if (prod != null)
                        productEnt = new ProductEntity()
                        {
                            ProductID = prod.ProductID,
                            ProductName = prod.ProductName,
                            QuantityPerUnit = prod.QuantityPerUnit,
                            UnitPrice = (decimal)prod.UnitPrice,
                            UnitsInStock = (int)prod.UnitsInStock,
                            ReorderLevel = (int)prod.ReorderLevel,
                            UnitsOnOrder = (int)prod.UnitsOnOrder,
                            Discontinued = prod.Discontinued
                        };
                }
                return productEnt;
        }
        public bool UpdateProduct(ProductEntity product)
        {
            bool updated = true;
            using (var NWEntities = new NorthwindEntities())
            {
                var productID = product.ProductID;
                Product productInDB = (from p in NWEntities.Products
                                       where p.ProductID == productID
                                       select p).FirstOrDefault();
                if (productInDB == null)
                {
                    throw new Exception("No product with ID " + product.ProductID);
                }
                NWEntities.Products.Remove(productInDB);
                productInDB.ProductName = product.ProductName;
                productInDB.QuantityPerUnit = product.QuantityPerUnit;
                productInDB.UnitPrice = product.UnitPrice;
                productInDB.Discontinued = product.Discontinued;
                NWEntities.Products.Attach(productInDB);
                NWEntities.Entry(productInDB).State = System.Data.EntityState.Modified;
                int num = NWEntities.SaveChanges();
                if (num != 1)
                {
                    updated = false;
                }
            }
            return updated;
        }
        #endregion
    }
}

Using the Code

The Conversion

The interaction of REST is done through a standard uniform interface or service contract. In this case, it would be the methods defined by the HTTP protocol specifically GET, POST, PUT, and DELETE. By standardizing on the uniform interface, developers can build infrastructure around the semantic meaning of each operation and make performance and scalability improvements when possible. For security, REST simply uses HTTPS; it just leverages SSL for all its security needs.

We will start with the three operations: GetAllProducts, which returns all products, GetProductByID where we provide a productID for the product that we are looking for, and finally, UpdateProduct will demonstrate the WebInvoke operation which is passing the PUT method.

First, we need to add the ServiceModel.Web assembly which gives us access to the WebGet and WebInvoke methods. The following is the step by step instruction for converting the IProduct interface:

  1. In the Product interface, let’s define our URI mapping which specifies what URI to map to; for instance,[WebGet(UriTemplate = "products")] for the GetAllProducts method
  2. For the GetProductByID, we will need to pass in the base address, followed by the product, then followed by the productID – [WebGet(UriTemplate = "product/{productID}")]
  3. WebInvoke uses the same property. The update/submit method uses the POST method; for instance,[WebInvoke(Method = "POST", UriTemplate = "product")]

Your complete code should look like the following (as you can see, the difference with SOAP-based is just around the interface):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.ServiceModel.Syndication;

namespace SoapToRESTfullDemo
{
    [ServiceContract]
    public interface IProductService
    {
        [WebGet(UriTemplate = "products")]
        [OperationContract]
        List<ProductEntity> GetAllProducts();

        //UriTemplate - the base address, followed by product and followed by the ID
        [WebGet(UriTemplate = "product/{productID}")] 
        [OperationContract]
        ProductEntity GetProductByID(string productID);
                
        //WebInvoke has the same property - for update/submit use POST. Post it to product
        [WebInvoke(Method = "POST", UriTemplate = "product")]
        [OperationContract]
        bool UpdateProduct(ProductEntity product);
    }

    [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
    public class ProductService : IProductService
    {
        #region IProductService Members
        public List<ProductEntity> GetAllProducts()
        {
            List<ProductEntity> products = new List<ProductEntity>();
            ProductEntity productEnt = null;
            using (var NWEntities = new NorthwindEntities())
            {
                List<Product> prods = (from p in NWEntities.Products
                                 select p).ToList();
                if (prods != null)
                {
                    foreach (Product p in prods)
                    {
                        productEnt = new ProductEntity()
                        {
                            ProductID = p.ProductID,
                            ProductName = p.ProductName,
                            QuantityPerUnit = p.QuantityPerUnit,
                            UnitPrice = (decimal)p.UnitPrice,
                            UnitsInStock = (int)p.UnitsInStock,
                            ReorderLevel = (int)p.ReorderLevel,
                            UnitsOnOrder = (int)p.UnitsOnOrder,
                            Discontinued = p.Discontinued
                        };
                        products.Add(productEnt);
                    }
                }
            }
            return products;
        }

        public ProductEntity GetProductByID(string productID)
        {
            int pID = Convert.ToInt32(productID);
            ProductEntity productEnt = null;
            using (var NWEntities = new NorthwindEntities())
            {
                Product prod = (from p in NWEntities.Products
                                where p.ProductID == pID
                                select p).FirstOrDefault();
                if (prod != null)
                    productEnt = new ProductEntity()
                    {
                        ProductID = prod.ProductID,
                        ProductName = prod.ProductName,
                        QuantityPerUnit = prod.QuantityPerUnit,
                        UnitPrice = (decimal)prod.UnitPrice,
                        UnitsInStock = (int)prod.UnitsInStock,
                        ReorderLevel = (int)prod.ReorderLevel,
                        UnitsOnOrder = (int)prod.UnitsOnOrder,
                        Discontinued = prod.Discontinued
                    };
            }
            return productEnt;
        }
        public bool UpdateProduct(ProductEntity product)
        {
            bool updated = true;
            using (var NWEntities = new NorthwindEntities())
            {
                var productID = product.ProductID;
                Product productInDB = (from p in NWEntities.Products
                                       where p.ProductID == productID
                                       select p).FirstOrDefault();
                if (productInDB == null)
                {
                    throw new Exception("No product with ID " + product.ProductID);
                }
                NWEntities.Products.Remove(productInDB);
                productInDB.ProductName = product.ProductName;
                productInDB.QuantityPerUnit = product.QuantityPerUnit;
                productInDB.UnitPrice = product.UnitPrice;
                productInDB.Discontinued = product.Discontinued;
                NWEntities.Products.Attach(productInDB);
                NWEntities.Entry(productInDB).State = System.Data.EntityState.Modified;
                int num = NWEntities.SaveChanges();
                if (num != 1)
                {
                    updated = false;
                }
            }
            return updated;
        }
        #endregion
    }
}

Once we have the interface modified, we can then modify the configuration file (app.config) to wire up the service. The following are the steps for modifying the app.config:

  1. Change binding from basic to WebHttpBinding – <endpoint address ="" binding="wsHttpBinding" contract="SoapToRESTfullDemo.IProductService">
  2. Add a new behavior – <behavior name="SoapToRESTfullDemo.Service1Behavior">
  3. Apply this behavior to the service – <service name="SoapToRESTfullDemo.ProductService" behaviorConfiguration="SoapToRESTfullDemo.Service1Behavior">

Your app.config should look like the following:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <compilation debug="true" />
  </system.web>
  <!-- When deploying the service library project, 
  the content of the config file must be added to the host's 
  app.config file. System.Configuration does not support config files for libraries. -->
  <system.serviceModel>
    <services>
      <service name="SoapToRESTfullDemo.ProductService" 
               behaviorConfiguration="SoapToRESTfullDemo.Service1Behavior">
        <host>
          <baseAddresses>
            <add baseAddress = "http://localhost:8888/products" />
          </baseAddresses>
        </host>
        <!-- Service Endpoints -->
        <!-- Unless fully qualified, address is relative to base address supplied above -->
        <endpoint address ="" binding="wsHttpBinding" 
              contract="SoapToRESTfullDemo.IProductService">
          <!-- 
              Upon deployment, the following identity element 
              should be removed or replaced to reflect the 
              identity under which the deployed service runs. 
              If removed, WCF will infer an appropriate identity 
              automatically.
          -->
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <!-- Metadata Endpoints -->
        <!-- The Metadata Exchange endpoint is used by the 
                service to describe itself to clients. -->
        <!-- This endpoint does not use a secure binding and 
                should be secured or removed before deployment -->
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="SoapToRESTfullDemo.Service1Behavior">
          <!-- To avoid disclosing metadata information, 
          set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="True"/>
          <!-- To receive exception details in faults for debugging purposes, 
          set the value below to true.  Set to false before deployment 
          to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
  <connectionStrings>
    <add name="NorthwindEntities" 
      connectionString="metadata=res://*/Northwind.csdl|res://*/Northwind.ssdl|res://
        */Northwind.msl;provider=System.Data.SqlClient;provider connection 
        string="data source=IDALTW76S51DS1;initial catalog=Northwind;
        integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" 
      providerName="System.Data.EntityClient" />
  </connectionStrings>
</configuration>

Running the REST Service

We basically expose the same functionality as we did using SOAP, but these functionalities are exposed through the standard HTTP uniform service contract. The URI will determine which functionality is being invoked. Let’s start by running the host. As seen in the following image, the host displays the base address, which is specified in the configuration file (http://localhost:8080/productservice).

Now, we can see the service invocation by typing in the full address in the Web browser; such ashttp://localhost:8080/productservice/products. This address will display the following result for the GetAllProducts(remember the UriTemplate is calling for “products”):

When calling GetProductByID, we will need to pass in the product ID as part of the query string; for instance,http://localhost:8080/product/productID. The following is the result, which returns only a product with an ID of 1:

Summary

This turns out to be extremely advantageous when building highly scalable web applications and services. Now we are able to represent resources using a concrete representation. A message format such as XML, RSS, JSON, etc. So, when we work with our resources when we request them or update them or create them, we’re going to be passing a representation of that resource at a particular point in time.

Although we can summarize things by saying that SOAP is usually a better fit within the enterprise, whereas REST is usually a better fit within public web facing service scenarios where you need a high degree of scalability and interoperability. The good news is WCF provides a programming model that accommodates each of these different styles and a variety of different message formats.

Ref: http://www.codeproject.com/Articles/590627/Converting-SOAP-based-WCF-Service-to-RESTful-Desig

[Discovery] Tại sao chúng ta phải tắt điện thoại, dựng thẳng lưng ghế, kéo cửa sổ khi máy bay cất/hạ cánh

cài_dây_an_toàn.
Khi đi máy bay, chúng ta thường được tiếp viên nhắc nhở: “Tắt nguồn điện thoại di động và các thiết bị điện tử cầm tay, mở tấm che cửa sổ, dựng thẳng lưng ghế, gập bàn ăn và thắt dây an toàn” mỗi khi máy bay cất/hạ cánh. Tại sao chúng ta được yêu cầu như vậy và nó ảnh hưởng gì đến an toàn bay thì hôm nay, chuyên mục “Tại sao?” sẽ tiếp tục cùng bạn đi tìm câu trả lời.

Tại sao phải tắt nguồn điện thoại di động và thiết bị điện tử?

Từ năm 1991, Ủy ban truyền thông liên bang Mỹ (FCC) đã ban hành lệnh cấm sử dụng các thiết bị điện tử cá nhân bao gồm cả điện thoại di động trên máy bay mặc dù vào thời điểm đó Cơ quan hàng không liên bang Mỹ (FAA) trên thực tế lại không cấm sử dụng các thiết bị điện tử cá nhân. Đây là một vấn đề gây tranh cãi đến nay vẫn chưa có hồi kết.

Lý do hàng đầu được FCC đưa ra là hoạt động của các thiết bị có thể phát ra sóng vô tuyến gây nhiễu hệ thống điện tử nhạy cảm của máy bay. Máy bay được trang bị một loạt các hệ thống điện tử cho phép phi công và bản thân máy bay liên lạc với mặt đất, hỗ trợ định hướng và giám sát các trang thiết bị khác. Các hệ thống này được gọi là hệ thống điện tử hàng không. Rất nhiều thành phần trong hệ thống sử dụng tín hiệu radio để gởi nhận thông tin do đó chúng tiềm năng bị nhiễu bởi các thiết bị phát sóng sử dụng tần số radio tương tự. Bức xạ tần số radio còn có khả năng ảnh hưởng đến dòng điện trong các dây dẫn do đó hệ thống điện tử hàng không có thể bị ảnh hưởng. Mặc dù đến nay vẫn chưa có bằng chứng rõ ràng cho thấy tác động của các thiết bị điện tử đối với hoạt động của máy bay nhưng lệnh cấm này vẫn tồn tại và nhiều hãng hàng không trên thế giới đã hưởng ứng theo phương châm “an toàn là trên hết.”

Thêm vào đó, giai đoạn cất cánh và hạ cánh của máy bay được xem là 2 giai đoạn quan trọng nhất đối với mỗi chuyến bay và đòi hỏi phi hành đoàn phải tập trung cao độ, duy trì liên lạc với trạm kiểm soát không lưu ATC và đảm bảo hoạt động của tất cả các trang thiết bị trên máy bay. Giai đoạn cất cánh và hạ cánh được xác định khi máy bay đang bay dưới 10,000 ft (~ 3048 m) và trung bình một chiếc máy bay sẽ mất khoảng từ 15 đến 20 phút để đạt độ cao này. Do đó, giới hạn sử dụng thiết bị điện tử sẽ nằm trong khoảng thời gian bắt đầu và kết thúc chuyến bay.

thiết_bị_được_dùng.

Điện thoại di động dĩ nhiên bị cấm sử dụng hoàn toàn trên chuyến bay. Khi được yêu cầu tắt nguồn hay đưa máy về chế độ Airplane Mode có nghĩa thiết bị phải được đảm bảo ngắt hoàn toàn các kết nối vô tuyến. Các thiết bị điện tử khác như máy nghe nhạc, máy chơi game, laptop v.v… phải được tắt trong giai đoạn cất và hạ cánh. Các thiết bị như máy trợ tim, trợ thính, dao cạo râu chạy điện vẫn được sử dụng bởi chúng không gây nhiễu.

Ngoài việc loại trừ nguy cơ gây nhiễu thì việc cấm sử dụng thiết bị điện tử cũng ngăn ngừa khả năng gây tổn thương cho hành khách trong trường hợp máy bay dằn xóc khi đi vào vùng thời tiết xấu, thiết bị có thể bị hất văng gây nguy hiểm. Bên cạnh đó, việc cấm sử dụng các thiết bị điện tử cá nhân trong quá trình cất hạ cánh cũng giúp cho hành khách tập trung theo dõi các chỉ dẫn an toàn bay hơn và phi hành đoàn cũng không bị phân tâm khi thực hiện nhiệm vụ của mình.

đt_trên_máy_bay_01.

Ngoài ra, FCC còn đưa ra một lý do nữa là hoạt động của điện thoại di động hay các thiết bị thu phát sóng có thể gây nhiễu mạng lưới truyền thông dưới đất. Khi bạn thực hiện một cuộc gọi ở độ cao dưới 10,000 ft, tín hiệu sẽ được truyền đi qua hàng loạt các cột phát sóng di động thay vì chỉ 1 và nếu có nhiều người cùng thực hiện cuộc gọi, mạng lưới truyền thông dưới đất sẽ bị tắt nghẽn. Về phía FAA, cơ quan hàng không liên bang Mỹ khuyến nghị hành khách nên chuyển về chế độ Airplane Mode bởi ở độ cao 30,000 ft (~ 9144 m), điện thoại không thể nhận được tín hiệu di động và nếu cứ liên tục dò tìm tín hiệu thì điện thoại sẽ nhanh chóng hết pin khi bạn hạ cánh.

thiết_bị_Bluetooth.

Vào tháng 8 năm 2012, FAA đã bắt đầu xem xét việc nới lỏng sử dụng các thiết bị điện tử cá nhân trên máy bay mặc dù điện thoại vẫn bị cấm. Đến tháng 10 năm 2013, FAA đã công bố rằng các hãng hàng không có thể xem xét cho phép hành khách sử dụng thiết bị điện tử cầm tay một cách an toàn trong tất cả các giai đoạn của chuyến bay. Điện thoại có thể được sử dụng với các chức năng giải trí và phải đưa về chế độ Airplane Mode hoặc tắt kết nối di động, không được dùng tính năng liên lạc theo lệnh cấm của FCC. Kết nối Bluetooth tầm ngắn vẫn được cho phép, bạn có thể dùng các thiết bị ngoại vi như bàn phím Bluetooth. Nếu hãng hàng không có cung cấp dịch vụ Wi-Fi trên chuyến bay, hành khách vẫn có thể sử dụng các dịch vụ này. Trong quá trình cất/hạ cánh, thiết bị điện tử phải được giữ chặt trên tay hoặc đặt vào túi ghế phía trước.

Tuy nhiên, chúng ta cần lưu ý rằng mỗi hãng hàng không được phép đưa ra các quy định riêng và cũng tùy theo luật pháp của từng quốc gia mà hành vi sử dụng điện thoại hay các thiết bị điện tử trên máy bay có bị cấm hay không. Do đó khi đi máy bay của hãng hàng không nào thì bạn phải tuân thủ quy định của hãng cũng như luật pháp tại quốc gia mà chuyến bay cất/hạ cánh. Tại Việt Nam, cả 3 hãng hàng không hiện tại đều cấm sử dụng điện thoại di động trên máy bay và cho phép sử dụng một số thiết bị điện tử sau khi máy bay đã ổn định độ cao.

Tại sao phải mở cửa sổ?

mở_cửa_sổ.

Bên cạnh việc phải tắt điện thoại di động và các thiết bị điện tử khi máy bay cất và hạ cánh thì điều tiếp theo bạn phải làm là mở ô cửa sổ hay cụ thể là tấm che cửa sổ. Đôi khi ánh sáng bên ngoài quá chói khiến bạn cảm thấy khó chịu nhưng chúng ta buộc phải thực hiện điều này theo yêu cầu của tiếp viên. Tại sao?

Chúng ta có một số giải đáp theo gợi ý của nhiều người dùng trên trang stackexchange:

  • Hành khách rất tò mò do đó họ sẽ nhanh chóng phát hiện ra điều bất thường bên ngoài, chẳng hạn như một dấu hiệu hỏng hóc trên cánh, động cơ hay vật thể lạ và thông báo ngay cho tổ bay. Và để làm điều này, các cửa sổ trên máy bay được yêu cầu phải mở.
  • Trong trường hợp khẩn cấp, thời gian thoát khỏi máy bay sẽ được tính bằng giây. Nếu tấm che cửa sổ được mở, phi hành đoàn có thể quan sát điều kiện bên ngoài và điều này giúp họ lên kế hoạch sơ tán, chẳng hạn như phải sử dụng cửa thoát hiểm nào.
  • Trong các chuyến bay ban ngày, việc mở cửa sổ và mở tối đa ánh sáng trong cabin sẽ giúp mắt người làm quen với ánh sáng tốt hơn. Điều này có nghĩa nếu có điều gì bất thường và hành khách cần phải được sơ tán nhanh chóng thì độ tương phản ánh sáng sẽ không bị thay đổi đột ngột và hành khách không bị ảnh hưởng đến thị lực.
  • Vào ban đêm, tấm che cửa sổ được mở, ánh sáng trong cabin được giảm xuống giúp các nhân viên cứu hộ dưới mặt đất có thể quan sát những gì xảy ra bên trong cabin dễ dàng từ bên ngoài.
  • Hành khách được yêu cầu mở tấm che cửa sổ trước khi cất/hạ cánh bởi đây là những giai đoạn quan trọng trong mỗi chuyến bay và hầu hết các tai nạn hàng không đều xảy ra trong giai đoạn này.

Tại sao phải dựng thẳng lưng ghế, gập bàn ăn và thắt dây an toàn?

dựng_thẳng_lưng_ghế.

Có 2 lý do chính rất đơn giản khi bạn được yêu cầu dựng thẳng lưng ghế. Thứ nhất, khi bạn dựng thẳng ghế, vị trí ghế được khóa lại và ngược lại, khi bạn ngã lưng ghế ra phía sau, vị trí ghế không được khóa. Đây là cơ chế hoạt động của mọi ghế trên máy bay và bạn cũng đã quá quen thuộc với việc phải bấm nút trên chỗ để tay để nhả khóa và ngã lưng ghế ra sau. Trong trường hợp khẩn cấp, một chiếc ghế không được khóa cố định sẽ chịu nhiều lực tác động hơn và lưng ghế bật về phía trước sẽ gây nguy hiểm cho chính người ngồi trên ghế cũng như người ngồi phía sau.

Thứ 2, người ngồi đằng sau chiếc ghế không được dựng thẳng lưng sẽ không thể có được tư thế trụ vững nhất trong trường hợp va chạm. Có rất nhiều cách để chống trụ cơ thể khi máy bay gặp va chạm và vào cuối những năm 1980, FAA cũng đã nghiên cứu nhiều phương pháp để hành khách chuẩn bị tư thế đón nhận va chạm. Trước khi một chiếc máy bay dân dụng được chứng nhận, nhà sản xuất phải chứng minh rằng nó có thể cho phép hành khách sơ tán nhanh chóng. Vì lý do này, phần 121.311(d) luật hàng không liên bang Mỹ yêu cầu lưng ghế trên máy bay phải có cơ chế khóa an toàn.

bàn_ăn.

Về chiếc bàn ăn, có 2 lý do đơn giản buộc bạn phải gập gọn nó lại khi máy bay cất/hạ cánh. Thứ nhất, bàn ăn được gập gọn sẽ tạo khoảng trống, giúp bạn cũng như người ngồi cạnh sơ tán nhanh hơn trong trường hợp khẩn cấp. Thứ 2, khi va chạm xảy ra, nếu bạn không thắt chặt dây an toàn, cơ thể bạn có thể trượt về phía trước, đập vào bàn ăn và các cơ quan nội tạng có thể bị tổn thương.

cài_dây_an_toàn.

Về phần dây an toàn thì chức năng của nó chúng ta đều đã biết. Dây an toàn giúp giữ cố định cơ thể với ghế và giảm thiểu chấn thương khi máy bay bị dằn xóc hay va chạm. Hành khách có thể được tháo dây an toàn khi máy bay đã đạt độ cao ổn định nhưng bắt buộc phải cài dây trong quá trình cất/hạ cánh và mỗi khi đèn hiệu cài dây an toàn được bật sáng.

Một số hành khách thường xem thường yêu cầu này và bản thân mình từng chứng kiến một trường hợp suýt tai nạn do không cài dây an toàn. Trong một lần đi máy bay về Đà Nẵng, mặc dù máy bay đã đạt độ cao ổn định nhưng đèn hiệu cài dây vẫn bật sáng. Có một hành khách nữ cần sử dụng WC nhưng tiếp viên không cho phép rời ghế và yêu cầu vẫn cài dây do đèn hiệu này chưa được tắt đi. Tiếp viên nhiệt tình giải thích rằng mặc dù đã đạt độ cao nhưng cơ trưởng vẫn chưa tắt đèn báo hiệu cài dây an toàn do khả năng máy bay sẽ đi vào vùng thời tiết xấu. Chị đó đã phớt lờ lời cảnh báo, không cài dây an toàn và kết quả là máy bay xóc mạnh khi bay vào vùng nhiễu động khí khiến chị này suýt chút nữa là ngã ra khỏi ghế. Các bạn hẳn cũng từng gặp phải tình huống tương tự khi đi máy bay và lời khuyên chân thành là các bạn nên cài dây mỗi khi đèn báo bật sáng đề phòng tai nạn đáng tiếc.

Nguồn: Tổng hợp

[Discovery] Sơ lược lịch sử phát triển 80 năm của đồng hồ thông minh

BANNER_Apple_Watch_1.

Thời gian gần đây, sự ra mắt của hàng loạt đồng hồ thông minh từ nhiều hãng công nghệ luôn nhận được sự chú ý của những người yêu công nghệ. Nhưng liệu khái niệm đồng hồ thông minh có thật sự mới? Bạn có biết rằng chiếc đồng hồ thông minh đầu tiên đã xuất hiện cách đây gần 80? Thời gian đầu, những chiếc đồng hồ “thông minh” ra sao? Bài viết này sẽ ngược dòng thời gian nhằm tìm lời giải đáp cho những câu hỏi đó.

Trên thực tế, ý tưởng thiết bị hiện đại đeo trên cổ tay không phải là một ý tưởng mới lạ. Tuy nhiên, nếu mở rộng khái niệm như thế nào là “thông minh” thì đồng hồ thông minh cũng có bề dày lịch sử với sự tham gia của nhiều hãng, nhiều mẫu mã khác nhau. Ở góc độ bài viết này, chúng ta sẽ đi tìm những chiếc đồng hồ, ngoài khả năng xác định thời gian ra, thì nó còn có thêm tính năng tính toán, lưu trữ dữ liệu, lên kế hoạch, có khả năng chạy các đoạn mã lập trình, phát nhạc (không phải là báo thức) và có thể là chơi được cả file video hoặc thu/phát tín hiệu radio.” Ngoài ra, những thiết bị khác, bao gồm cả những thiết bị có hình thức giống đồng hồ, nhưng không được dùng để đeo thì sẽ không được liệt kê ra ở bài viết này.

Tóm tắt các sự kiện đáng chú ý trong quá trình phát triển đồng hồ thông minh
Screen Shot 2014-09-15 at 14.06.16.

Những năm 1940 đến đầu 1980: Giai đoạn đầu với tính năng thực hiện phép tính và giải trí

mimologa.
Mimo-Loga, chiếc đồng hồ “thông minh” đầu tiên ra đời năm 1940​

Với các tiêu chí được đặt ra ở trên, chiếc đồng hồ thông minh đầu tiên là Mimo-Loga được giới thiệu tại miền La Chaux-de-Fonds, Thụy Sĩ vào năm 1940. Mimo Loga được trang bị thêm 2 vòng có thể xoay được, chứa thang đo logarit ở viền mặt đồng hồ cho phép người đeo có thể thực hiện các phép tính đơn giản. Dù đây chỉ là đồng hồ cơ khí bình thường và không có sự hỗ trợ của điện từ nhưng đây được xem là chiếc đồng hồ đầu tiên có khả năng tính toán. Mimo Loga nhanh chóng được sự đón nhận của người dùng và trở thành một tiêu chuẩn của các đồng hồ cơ dành cho phi công.

Vài tuần sau đó, dựa trên ý tưởng trên, hãng đồng hồ nổi tiếng tại Thụy Sĩ, Breitling chính thức nhận được bằng sáng chế cho thiết kế đồng hồ đo thời gian (chronograph) dùng để đo khoảng thời gian của một sự kiện nào đó. Trong tiếng Hy Lạp, 2 từ “chronos” và “graph” có nghĩa là “thời gian” và “ghi, viết.” Đây là tính năng trên đồng hồ cơ và không được xem như một chức năng “thông minh” do các thao tác tính toán đều được người đeo thực hiện bằng tay và về cơ bản, các thang đo, quy tắc trên mặt đồng hồ chỉ là một bảng tra cứu. Tuy nhiên, tính năng đo thời gian cũng có ảnh hưởng đến lịch sử của đòng hồ thông minh do đây là tiền đề cho sự ra đời của những chiếc đồng hồ có trang bị máy tính điện tử.

smartwatch_03-100025797-gallery.
Pulsar và Pulsar Calcron, chiếc đồng hồ thông minh với màn hình LED và phím hỗ trợ chức năng tính toán các phép tính đơn giản​

Mùa thu năm 1972, công ty Hamilton Pulsar (thương hiệu đồng hồ đến từ Mỹ, một bộ phận của Tập đoàn Seiko) chính thức giới thiệu nguyên mẫu đồng hồ LED. Đây là chiếc đồng hồ điện tử đầu tiên trên thế giới hiển thị thời gian dưới dạng kỹ thuật số. Vào thời điểm bấy giờ, 1 chiếc đồng hồ LED Pulsar làm bằng vàng 18k có giá bán là 2100 đô la Mỹ. Tuy nhiên, một thiết bị đeo trên cổ tay được gọi là “thông minh” lại là Calcron, được hãng Pulsar giới thiệu vào năm 1975. Về cơ bản, Calcron là một chiếc máy tính điện tử đeo trên cổ tay cho phép người dùng thực hiện các phép tính đơn giản như cộng trừ nhân chia, tính phần trăm. Tuy nhiên, người dùng phải sử dụng một cây bút nhỏ để bấm vào các nút bấm được bố trí chìm dưới bề mặt đồng hồ để nhập các lệnh tính toán. Đồng thời, dù mang tên là đồng hồ nhưng Calcron không có khả năng xem giờ mà màn hình được dùng toàn bộ để thực hiển thị các con số tính toán.

uranus.
Đồng hồ Uranus, cũng hỗ trợ thực hiện phép tính nhưng các phím số được bố trí thuận tiện hơn​

Một nhà sản xuất khác cũng đã phát triển thành công đồng hồ hỗ trợ máy tính điện tử là Uranus. Tương tự như Calcron, mẫu đồng hồ của Uranus cũng có hỗ trợ thực hiện các phép tính đơn giản nhưng các nút bấm được bố trính lồi lên xung quanh màn hình nhằm thuận tiện hơn trong quá trình sử dụng. Vào năm 1977, hãng HP chính thức giới thiệu HP-01, mẫu đồng hồ hỗ trợ việc đếm thời gian, tính toán và đồng hồ bấm giờ. HP-01 được xem là mẫu đồng hồ “thông minh” nhất từng được sản xuất tính đến thời điểm bấy giờ.

seiko-c153.
Đồng hồ Seiko C153 ra đời năm 1977 với đầy đủ các chức năng tính toán và hỗ trợ màn hình 3 dòng để hiển thị thông tin​

Tuy nhiên, không lâu sau khi ra đời, các thế hệ đồng hồ LED đã nhanh chóng bộc lộ khuyết điểm là tiêu thụ quá nhiều năng lượng và đa số cũng không có chức năng xem giờ. Trước tình hình đó, các hãng từ Nhật Bản chẳng những đã nhanh chóng giải quyết được vấn đề bằng công nghệ LED thế hệ mới mà còn bổ sung thêm một số tính năng giúp đồng hồ trở nên “thông minh” hơn. Năm 1977, hãng Seiko giới thiệu mẫu đồng hồ Seiko C153 có đầy đủ chức năng của một máy tính khoa học phổ thông với 3 dòng thông tin trên màn hình. Tiếp theo đó là những chiếc đồng hồ tương tự như Citizen 49-9421 cal. 9140A hay nhiều mẫu đồng hồ của Casio.

ultra-raro-casio-game-gm-30-de-1980-10-20-30-40-301-401-14528-MLB198687801_9751-O.
Mẫu đồng hồ Casio-Game 30 hỗ trợ chơi các trò chơi đơn giản​

Vào năm 1980, Casio chính thức giới thiệu chiếc đồng hồ Casio Game-10, Game-30,… có hỗ trợ những trò chơi đơn giản trên màn hình. Thậm chí trong những năm 1980, Casio còn giới thiệu các mẫu đồng hồ “thông minh” hơn, có hỗ trợ chức năng nghe nhạc (chỉ là những đoạn nhạc chuông đơn giản) như mẫu Casio M-14 vào năm 1986 hoặc mẫu Casio TM-100 cho phép truyền tải âm thanh qua sóng Radio vào năm 1987. TM-100 được tích hợp một cái anten, microphone cho phép truyền âm thanh thu được từ đồng hồ tới các máy thu sóng FM gần đó.

casio-tm-100-4.
Đồnh hồ Casio TM-100 cho phép truyền tải âm thanh qua sóng Radio ra đời vào năm 1987​

Tuy nhiên, tất cả những mẫu đồng hồ trong giai đoạn này đều chưa thật sự thông minh do các chức năng đều gói gọn bên trong chiếc đồng hồ. Nó vẫn chưa có khả năng thông tin liên lạc, chỉ cho phép sử dụng những chức năng có sẵn và người dùng chưa thể lưu trữ các dữ liệu cần thiết. Và dĩ nhiên, giai đoạn tiếp theo vào cuối những năm 1980, đầu 1990 thì những chiếc đồng hồ chắc chắn sẽ “thông minh” hơn nữa.

Từ 1980 đến cuối những năm 1990 : Lưu trữ dữ liệu, lập trình, đa phương tiện và truyền thông

Nếu như cho đến cuối những năm 1970, đầu những năm 1980, đồng hồ đã có thể nghe những âm thanh có giai điệu đơn giản, chơi một số trò chơi, hỗ trợ tính toán khoa học,… nhưng nó vẫn chưa thể thật sự thông minh. Tất cả những gì người dùng có thể làm là thao tác với những gì được nhà sản xuất cài sẵn và sau đó lại trở lại màn hình xem giờ bình thường. Tuy nhiên, đối với các hãng điện tử Nhật Bản thì cuộc chơi chỉ mới bắt đầu.

seiko_409.
Nguyên mẫu đồng hồ Seiko D409, lần đầu tiên có khả năng lưu trữ dữ liệu dung lượng 112 byte, khơi mào cho sự phát triển của các đồng hồ lưu dữ liệu (databank)​

Vào năm 1982, Seiko chính thức giới thiệu nguyên mẫu đồng hồ D409 có tích hợp bộ nhớ lưu trữ dữ liệu. D409 chỉ có bộ nhớ dung lượng 112 bytes và chỉ cho phép người dùng lưu thông tin vào mục “ghi nhớ” trên đồng hồ. Tính năng “ngân hàng dữ liệu” (databank) nhanh chóng được các hãng đồng hồ khác chú ý và tích hợp vào trong các mẫu đồng hồ sau đó. Thậm chí, một số đồng hồ còn đi kèm với một bàn phím rời cho phép người dùng nhập dữ liệu thuận tiện hơn. Dù vậy, các đồng hồ databank chỉ có chức năng lưu trữ, hiển thị thông tin và tính năng này vẫn chưa hoạt động thật sự hữu hiệu.

seiko-TV-watch-1-1600-WP.
Seiko TV Watch ra mắt vào năm 1982 đi kèm với phụ kiện thu sóng truyền hình cho phép xem TV ngay trên màn hình​

Một số mẫu đồng hồ đáng chú ý trong giai đoạn này còn có khả năng trình chiếu đa phương tiện. Điển hình như mẫu đồng hồ TV Watch của Seiko ra mắt vào năm 1982 với khả năng xem TV ngay trên màn hình. Dù vậy, màn hình của mẫu đồng hồ này có độ tương phản quá kém và người dùng còn phải trang bị thêm phụ kiện kèm theo để có thể nhận được tín hiệu TV. Tuy khá bất tiện trong việc sử dụng, nhưng mẫu đồng hồ có khả năng xem TV cũng đã tạo nên một trào lưu mới về đồng hồ thông minh ở giai đoạn này.

Nhiều hạn chế về công nghệ màn hình LCD đã khiến các hãng dần từ bỏ việc trang bị màn hình trên đồng hồ thông minh. Thay vào đó, các ý tưởng trước đó như lưu trữ dữ liệu hay máy tính khoa học được các hãng tập trung hoàn thiện nhằm có thể hoạt động hoàn hảo hơn. Kết quả là những chiếc đồng hồ thế hệ tiếp theo ra đời với chức năng lưu trữ dữ liệu và tính toán đã có thể phối hợp cùng nhau để xử lý nhu cầu của người dùng. Dù vậy, tới đây thì chúng ta vẫn chưa có những chiếc đồng hồ có khả năng lập trình và cũng chưa có tính năng truyền thông.

smart-uc2000-580-90.
Seiko UC-2000, đồng hồ thông minh đi kèm với dock bàn phím nhập liệu và tích hợp máy in nhiệt​

Vào năm 1984, vấn đề lập trình đã được giải quyết một phần nhờ sự đóng góp cũng hãng Seiko. Đó là mẫu đồng hồ Data-2000 cho phép người dùng nhập ghi chú và đặc biệt là UC-2000, một chiếc máy vi tính đeo tay theo lời giới thiệu của hãng. Cả 2 mẫu đồng hồ đều được đi kèm với bàn phím nhập liệu, cho phép dữ liệu được nhập vào một cách dễ dàng hơn rất nhiều. UC-2000 sử dụng vi xử lý Z80, đi kèm với bàn phím kích thước khá lớn tích hợp máy in nhiệt, hỗ trợ chạy chương trình từ ROM. Phiên bản tiếp theo là UC-2200 đi kèm với bàn phím kích thước lớn hơn so với UC-2000, chạy trên nền tảng Microsft BASIC. Dù vậy, UC-2200 chỉ hỗ trợ đưa những phần mềm nhỏ do Seiko viết vào bộ nhớ RAM.

smart-RC1000-580-90.
Nguyên mẫu đồng hồ Seiko RC-1000 với khả năng truyền tải dữ liệu với máy tính thông qua cáp kết nối​

Dòng sản phẩm UC của Seiko tiếp tục tiếp nối bởi mẫu đồng hồ RC-1000 đi kèm với gói phần mềm hỗ trợ truyền tải dữ liệu với máy tính bằng dây cáp kết nối. Cùng với đó là mẫu Seiko UC-2001 được thiết kế dành riêng cho các máy tính Apple II. Đến thời điểm này, đồng hồ của Seiko đã có bộ nhớ 2kb để hỗ trợ lưu trữ các bản ghi chú hoặc danh mục. Giá của mỗi chiếc UC-2001 vào khoảng 500 đô la Mỹ và doanh số bán ra cũng không nhiều như dự kiến của Seiko.

epson_rc-20.
Một mẫu quảng cáo đồng hồ thông minh Epson RC-20 có thể trực tiếp chạy chương trình, hiển thị lên màn hình LCD​

Đến năm 1985, hãng Epson giới thiệu chiếc đồng hồ – máy vi tính hoạt động độc lập đeo tay đầu tiên mang tên Zilog Z80 RC-20. Người dùng đã có thể load các chương trình khác nhau vào ROM của RC-Z20 thông qua một phụ kiện đi kèm, sau đó trực tiếp chạy chương trình trên màn hình LCD ma trận điểm mà không cần có thiết bị hỗ trợ nào khác. Nói cách khác, đây được xem như chiếc đồng hồ đầu tiên có thể chạy ứng dụng một cách độc lập.

Trong giai đoạn đầu 1990, Seiko và Swatch đã phát triển nguyên mẫu đồng hồ nhắn tin đầu tiên, hỗ trợ truyền thông không dây trực tiếp giữa các đồng hồ. Vào năm 1990, Seiko chính thức giới thiệu đồng hồ Seiko Receptor sử dụng sóng thứ cấp tại các trạm thu phát radio để truyền gởi thông tin. Một năm sau đó, hãng Swatch cũng tung ra mẫu đồng hồ Beep dựa trên nguyên lý tương tự tại châu Âu. Cuối cùng vào năm 1995, hãng đồng hồ Timex cũng tung ra mẫu đồng hồ hỗ trợ truyền thông đầu tiên của hãng mang tên Beepwear.

timex-data-link.
Đồng hồ TImex Data Link 150, lần đầu tiên có thể giao tiếp không dây với máy tính thông qua kết nối quang học​

Đồng thời, chúng ta cũng phải kể tới mẫu đồng hồ Timex Data Link 150, chiếc đồng hồ đầu tiên có thể truyền tải dữ liệu không dây với máy tính. Với Data Link 150, người dùng có thể gởi các cuộc hẹn và thời gian báo thức từ máy tính lên đồng hồ thông qua cảm biến quang học trên mặt đồng hồ. Cuối thế kỷ 20 và cụ thể là năm 1998, Seiko chính thức tung ra đồng hồ Reputer, một chiếc máy tính có kích thước đồng hồ với CPU 16-bit, 3,6MHz, RAM 128kb và bộ nhớ 2MB. Giờ đây, người dùng đã có thể chạy các chương trình viết viết sẵn và hiển thị trên màn hình LCD 102x64px của đồng hồ. Cuối cùng, mẫu đồng hồ này được đổi tên thành Matsucom OnHand PC và chính thức bán ra tại thị trường Hoa Kỳ.

seiko_reputer.
Seiko Reputer, một chiếc máy tính có kích thước đồng hồ với CPU 16-bit, 3,6MHz, RAM 128kb và bộ nhớ 2MB, có thể chạy các chương trình viết viết sẵn và hiển thị trên màn hình LCD 102x64px​

Vậy là cho đến cuối những năm 1990, đồng hồ đã “thông minh hơn” với các khả năng lưu trữ dữ liệu, lập trình, đa phương tiện và truyền thông không dây. Tuy nhiên công nghệ không dừng lại ở đấy, vào những năm 2000, chúng ra sẽ chứng kiến những chiếc đồng hồ thông minh tương tự PDA, và nhiều chức năng khác cũng dần được bổ sung.

Những năm 2000: SPOT, PDA và kết nối không dây, sự xuất hiện của kết nối USB

ibm-lniux.
Đồng hồ IBM Linux Watch bộ nhớ RAM 8MB, bộ nhớ flash 8MB, sử dụng pin lithium-polymer​

Năm 2000 chứng kiến đóng góp đáng kể của IBM đối với sự phát triển của đồng hồ thông minh với chiếc đồng chạy hệ điều hành Linux. Tất cả những bộ phận bao gồm bộ nhớ RAM 8MB, bộ nhớ flash 8MB, viên pin lithium-polymer được gói gọn trong chiếc đồng hồ đeo trên cổ tay người dùng. 1 năm sau đó, IBM đã hợp tác với Citizen và tiếp tục cho ra mắt nguyên mẫu WatchPad 1.5 – chiếc đồng hồ duy nhất được trang bị CPU 74MHz ARM và chạy hệ điều hành Linux. Tuy cuối cùng thì WatchPad 1.5 không được thương mại hóa rộng rãi nhưng nó chính là một minh chứng quan trọng tạo tiền đề cho sự phát triển của đồng hồ thông minh ở các giai đoạn sau.


Video một số tính năng trên đồng hồ thông minh IBM Linux​

Cũng trong năm 2001 đã chứng kiến sự xuất hiện ngắn ngủi nhưng khá thú vị của một chiếc đồng hồ mang tên Web-@nywhere đến từ hãng World Network Limited có trụ sở đặt tại Hồng Kông. Đây là một chiếc đồng hồ với màn hình LCD 2 dòng hiển thị 18 ký tự. Người dùng sẽ sử dụng một chiếc dock đi kèm để kết nối chiếc đồng hồ với máy tính và sao chép những đoạn văn bản có kích thước 128kb từ các trang web xuống đồng hồ để đọc offline.

web.
Web-@nywhere đến từ hãng World Network Limited​

Tuy nhiên, chiếc đồng hồ này chỉ xuất hiện chủ yếu trên các catalog giới thiệu và không thể tạo được sức hút mạnh mẽ trên thị trường do khả năng hiển thị nội dung văn bản trên màn hình vẫn còn khá hạn chế.

Fossil FX2001 Wrist PDA (2002) .
Fossil FX2001 Wrist PDA, thiết bị PDA đeo cổ tay chạy Palm OS được giới thiệu năm 2002​

Nếu như cuối thế kỷ 20, chiếc đồng hồ Reputer của Seiko như một điểm sáng trong lịch sử phát triển đồng hồ thông minh thì vào đầu thế kỷ 21, một đối thủ cạnh tranh khác của nó là Fossil chính thức tham gia cuộc chơi. Fossil được biết đến rộng rãi với những mẫu đồng hồ thời trang. Trước xu thế phát triển chung của công nghệ, hãng đã quyết định phát triển những nguyên mẫu đồng hồ đầu tiên của hãng. Qua nhiều thử nghiệm ban đầu, cuối cùng thì vào năm 2002, hãng chính thức giới thiệu FX2001 Wrist PDA, thiết bị PDA đeo cổ tay chạy Palm OS.

Timex Ironman Data Link USB (2003) .
Timex Ironman Data Link USB một bản nâng cấp của Timex Data Link, cho phép cài đặt nhiều chương trình, kết nối với máy tính bằng cổng USB​

1 năm sau đó, vào năm 2003, hãng đồng hồ Timex đã nâng cấp dòng sản phẩm Data Link trước đó với phiên bản Timex Ironman Data Link USB. Chiếc đồng hồ này cho phép người dùng có thể cài đặt các chương trình khác nhau và hiển thị trên màn hình LCD ma trận điểm. Tuy nhiên, thay vì sử dụng cảm biến quang học như phiên bản trước đó, Timex Ironman sử dụng cáp USB để kết nối với máy tính nhằm cài thêm các ứng dụng, game, tiện ích sức khỏe do hãng cung cấp hoặc do bên thứ 3 phát triển.

bill-gates_va_spot.
Bill Gates đang giới thiệu nền tảng Smart Personal Objects Technology (SPOT) của Microsoft​

Một dự án khác cũng do Fossil thực hiện là chiếc đồng hồ Wrist .Net được giới thiệu chính thức vào năm 2004. Đây là thiết bị sử dụng công nghệ Smart Personal Objects Technology (SPOT), dùng sóng thứ cấp của các trạm thu phát sóng radio để nhận các thông tin tức thời từ dịch vụ MSN Direct do Microsoft cung cấp.

Fossil FX2008 Wrist PDA (2005) .
Fossil FX2008 Wrist PDA 2.0 ra mắt năm 2005​

Đến năm 2005, hãng Fossil tiếp tục giới thiệu phiên bản thứ 2 của chiếc đồng hồ chạy Palm OS với tên gọi Fossil FX2008 Wrist PDA 2.0. Dù phiên bản mới của Wirst PDA được trang bị thêm nhiều tính năng hơn nhằm đáp ứng các nhu cầu phức tạp của người dùng, nhưng phần cứng mà đặc biệt là màn hình đã quá lạc hậu so với thời điểm bấy giờ. Thêm vào đó, thời lượng pin của Wrist PDA 2.0 khá kém và một số người còn đánh giá là có độ bền không cao. Kết quả dĩ nhiên là không có nhiều sản phẩm được bán ra sau đó.

Dù vậy, sự phát triển của đồng hồ thông minh không phải do đó mà dừng lại và Fossil cũng không phải vì thất bại của Wrist PDA 2.0 mà bỏ cuộc. Bằng chứng là nhiều nguyên mẫu đồng hồ đã được Fossil nhanh chóng thiết kế và giới thiệu sau đó dưới 2 thương hiệu là Abacus và Sony Ericsson. Đó là những chiếc đồng hồ MBW-100, 150, 200,… với khả năng ghép đôi với điện thoại di động thông qua kết nối Bluetooth để đồng bộ thông tin trạng thái cuộc gọi đến, tin nhắn SMS, hiển thị bản nhạc đang phát,…

citizen_2007.
Một mẫu quảng cáo của Citizen Virt W700 ra mắt năm 2007 với khả năng kết nối bluetooth với điện thoại​

Năm 2007, hãng Citizen chính thức giới thiệu Virt W700 với khả năng kết nối bluetooth với điện thoại di động. Tuy nhiên, những chiếc đồng hồ đến từ hãng Nhật Bản này không giành được nhiều thành công tại các thị trường lớn trên thế giới.

lg_g910.
Đồng hồ thông minh LG GD910 được giới thiệu vào năm 2009​

Cuối cùng, để kết thúc giai đoạn này, chúng ta sẽ nhắc tới LG GD910, 1 trong những chiếc đồng hồ thông minh của LG với màn hình cảm ứng 1.3 inch, hỗ trợ kết nối 3G, gọi điện video và được tích hợp cả phần mềm nhận dạng giọng nói. Đây được xem như cải tiến đáng giá nhất về ngoại hình lẫn chức năng so với những mẫu đồng hồ thông minh trước đây. Đồng thời, cũng trong năm 2009, Samsung chính thức giới thiệu chiếc đồng hồ Samsung S9110. Về cơ bản, S9110 có màn hình 1,76 inch, độ phân giải 176x220px, hỗ trợ kết nối bluetooth, duyệt mail, trả lời tin nhắn thông qua màn hình cảm ứng và có thể thực hiện cuộc gọi một cách độc lập.

samsung-s9110.
Samsung S9110, chiếc đồng hồ thông minh được giới thiệu vào năm 2009​

Từ nằm 2010 đến nay: Kỷ nguyên của công nghệ hiện đại bắt đầu

Cuối cùng thì chúng ta đã đi tới chặng đường cuối cùng của bài viết, nhưng đây vẫn chỉ là những bước đi đầu tiên của công nghệ đồng hồ thông minh. Sau đây, chúng ta sẽ bắt gặp những chiếc đồng hồ ra mắt cách đây vài năm và thậm chí đang được bán ra trên thị trường. Từ năm 2010 đến nay, phần lớn những chiếc đồng hồ thông minh đều hỗ trợ kết nối tới thiết bị chủ thông qua Bluetooth nhằm hiển thị các thông báo. Một số chỉ là thiết bị hiển thị thông tin cuối, nhưng một số đã có hẳn một vi xử lý và chạy được các ứng dụng hoàn toàn độc lập.

LiveView_PHP-Top-Image.
Sony Ericsson LiveWiew được giới thiệu vào tháng 9 năm 2010​

Đầu tiên, mở đầu cho kỷ nguyên công nghệ hiện đại là Sony Ericsson LiveWiew được giới thiệu vào tháng 9 năm 2010. Đây là thiết bị sử dụng màn hình OLED, hỗ trợ hiển thị các widgets, nhận thông tin từ điện thoại. Các tính năng vẫn còn khá hạn chế và dĩ nhiên là không sánh bằng với những chiếc đồng hồ thông minh hiện nay.

ipod_nano_gen_6.
iPod Nano Gen 6, thiết bị có thể biến thành đồng hồ thông minh​

Cũng trong tháng 9 năm 2010, một thiết bị “tuy không chính thức” nhưng vẫn được xem như đại diện của đồng hồ thông minh chính là chiếc iPod Nano gen 6 của Apple. Tuy nhiên, với kích thước khá nhỏ gọn của iPod Nano, người dùng chỉ cần sử dụng thêm một chiếc vòng phụ kiện của bên thứ 3, dùng dây nhựa, dây da,…. là có thể đeo nó trên tay và dĩ nhiên nó sẽ trở thành đồng hồ thông minh đúng nghĩa.

allerta-inpulse-smartwatch.
Đồng hồ thông minh inPulse với màn hình OLED được hãng Allerta giới thiệu vào tháng 10 năm 2010​

Ngay sau đó, vào tháng 10 năm 2010, hãng Allerta chính thức giới thiệu chiếc đồng hồ thông minh inPulse với màn hình OLED, sử dụng chủ yếu cùng với các ứng dụng trên điện thoại BlackBerry. Bên cạnh đó, inPulse cũng có hỗ trợ sử dụng kèm với các thiết bị chạy Android. Đến tháng 8 năm 2012, WIMM One giới thiệu nguyên mẫu đồng hồ chạy Android với giao diện người dùng có tính tùy biến cao, hỗ trợ nhiều kiểu đồng hồ điện tử và số lượng widget khá đa dạng. Sử dụng màn hình LCD, phần cứng của WIMM One cũng được đánh giá là mạnh hơn so với các đồng hồ trước đó và điều đặc biệt là có hỗ trợ kết nối WIFI. Một điều đáng tiếc, đây chỉ là mẫu đồng hồ dành cho các nhà phát triển và được bán ra với số lượng vô cùng hạn chế.

motoactv-press-shot.
Motorola giới thiệu mẫu đồng hồ thông minh MOTOACTV vào tháng 11 năm 2011​

Tiếp theo là vào tháng 11 năm 2011, Motorola giới thiệu mẫu đồng hồ thông minh MOTOACTV và chính thức bước vào cuộc chơi đồng hồ thông minh như một xu hướng tất yếu của thị trường. MOTOACTV được trang bị vi xử lý đơn nhân tương tự như các mẫu điện thoại của Motorola và chạy hệ điều hành Android. Dù vậy, đây lại là một thiết bị được phát triển chủ yếu cho việc tập luyện thể thao và chơi media. Tuy nhiên, nó cũng hỗ trợ hiển thị các thông báo từ điện thoại Motorola. Một điểm chưa được hoàn hảo chính ở MOTOACTV chính là chiếc đồng hồ sẽ tự tắt màn hình và khi muốn sử dụng, người dùng phải mở lên bằng phím bấm.

SmartWatch_PP_ColorW_270x433.
SmartWatch được Sony giới thiệu vào tháng 2 năm 2012​

Đến tháng 2 năm 2012, Sony chính thức thay thế đồng hồ thông minh LiveView bằng SmartWatch, chếc đồng hồ được cải thiện cả về giao diện người dùng lẫn phần cứng bên trong. Dù vậy, màn hình sử dụng trên SmartWatch của Sony vẫn là màn hình OLED và vẫn phải tắt khi không sử dụng màn hình để tiết kiệm pin. Do đó, một số ý kiến vẫn chưa hài lòng với bản nâng cấp này của Sony. Cũng trong đầu năm 2012, Pebble Technology chính thức khởi động chương trình gây quỹ trên Kickstarter nhằm thương mại hóa một chiếc đồng hồ thông minh với màn hình E-ink.

pebble.
Pebble, chiếc đồng hồ màn hình E-ink được giới thiệu vào đầu năm 2012

Ngay sau đó, Pebble đã nhanh chóng gây được sự chú ý của thị trường bằng màn hình ít tiêu thụ điện năng, thời lượng pin dài, hỗ trợ đồng bộ với cả Android và iOS thông qua Bluetooth. Đồng thời, Pebble cũng có thể chạy các ứng dụng của bên thứ 3 phát triển. Ban đầu, nhóm phát triển chỉ dự định gây số quỹ tài trợ là 100.000 đô la Mỹ, nhưng con số này đã nhanh chóng vượt quá 10 triệu đô.

Moto-360_Map-820x420.
Moto360, một trong những chiếc đồng hồ thông minh chạy Android Wear​

Cách đây vài tháng, Google cũng đã chính thức giới thiệu nền tảng phần mềm cho đồng hồ thông minh mang tên Android Wear. Thay vì sản xuất những chiếc đồng hồ thông minh cho riêng mình, Google lại chọn cách như Android là tại ra nền tảng chung để tất cả các hãng khác đều có thể làm đồng hồ thông minh chạy Android Wear. Những hãng công nghệ lớn như Samsung, LG hay Motorola đều đã giới thiệu đồng hồ thông minh chạy Android Wear của riêng họ. Tựu chung, tất cả các thiết bị này đều hỗ trợ 2 chức năng trọng tâm là kết nối với điện thoại và hiển thị thông báo.

2585822_AppleWatch.

Cuối cùng, gần đây nhất là vào ngày 9/9 vừa qua, Tim Cook, CEO của Apple đã chính thức giới thiệu chiếc đồng hồ thông minh của hãng với tên gọi AppleWatch. AppleWatch có thiết kế unibody nguyên khối, chống nước, có nhiều tùy chọn dây đeo, màu sắc khác nhau và đáng chú ý mặt kính được làm bằng sapphire như các mẫu đồng hồ cao cấp khác. Như nhiều mẫu đồng hồ khác hiện nay, AppleWatch cũng được trang bị các loại cảm biến thông minh, núm điều chỉnh Digital Crown và đặc biệt là giao diện người dùng mang phong cách riêng của Apple.

Kết

span6.

Vậy là chúng ta vừa đi qua gần 80 năm lịch sử phát triển của những chiếc đồng hồ thông minh. Từ nguyên mẫu đồng hồ cơ ban đầu chỉ với viền có khắc thang đo logaric, đến những chiếc đồng hồ có thể tính toán phép tính được. Sau đó là hàng loạt những tính năng được bổ sung, từ xem TV, đa phương tiện, lưu dữ liệu, chạy ứng dụng,… cho đến những chiếc đồng hồ thông minh hiện nay với đủ các cảm biến theo dõi sức khỏe con người và đồng bộ một cách hiệu quả với smartphone.

Tất cả đều thông minh! Vậy chúng ta sẽ mong chờ gì đối với những chiếc đồng hồ trong tương lai? Có thể là pin xài được hơn 3 ngày, có thiết kế thời trang phù hợp với mắt thẩm mỹ của nhiều người, theo dõi sức khỏe của con người thông minh hơn, có thể sử dụng độc lập hoàn toàn với điện thoại, giao diện và cách dùng thân thiện với tất cả mọi người,… Đó chính là những mong muốn của mình đối với đồng hồ thông minh trong tương lai. Còn bạn thì sao? Hãy comment xuống bên dưới nhé. Cuối cùng cám ơn các bạn đã theo dõi bài viết này. Chúc vui. :D

Xem thêm các bài viết về những chiếc đồng hồ thông minh gần đây: