Dealing with Profile Access in ASP.NET MVC Applications

Introduction

ASP.NET services such as Profile are available to MVC applications too and developers can make use of them when needed. While developing a Web Forms based website project developers can access profile properties in a strongly typed fashion. This strongly typed nature comes from the ProfileCommon class that is generated automatically in such projects. ASP.NET MVC and Web Application projects, however, lack this handy and useful feature. In this article you will learn how to access user Profile in ASP.NET MVC applications and also an alternative to overcome this limitation.

Enabling Profile Features for an ASP.NET MVC Application

Before you deal with profile properties, you must configure a SQL Server database for storing membership and profile information. We will not be discussing these preliminary steps in this article. Read "Using Forms Authentication in ASP.NET MVC Applications" and follow the instructions to enable these features for your database. We will also skip detailed code level discussion of utilizing membership features as discussed in the above article. The source code accompanying this article includes all the necessary controllers and views that make use of membership features for authenticating the user. For the sake of this article, we will assume that you already have an ASP.NET MVC Application  with SQL Express database residing in the App_Data folder. The following figure shows the Solution Explorer with SQL Express database and other files.

Solution Explorer with SQL Express database
Figure 1: Solution Explorer with SQL Express database

Configuring a Profile Provider in ASP.NET MVC Application

In order to use Profile features you must configure a Profile provider in web.config file. Open web.config file and add the following markup under <system.web> section:

<profile enabled="true" defaultProvider="MyProfileProvider">

  <providers>

    <add name="MyProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="connstr" />

  </providers>

  <properties>

    <add name="FirstName" />

    <add name="LastName" />

  </properties>

</profile>

The <profile> section enables Profile features for your application and also defines a Profile provider - MyProfileProvider. Further, it defines two Profile properties viz. FirstName and LastName. You will be setting these Profile properties in the CreateUser() action method of MembershipController. Have a look at the following code fragment:

    [HttpPost]

    public ActionResult CreateUser(CreateUserData data)

    {

        MembershipCreateStatus status;

        Membership.CreateUser(data.UserID,data.Password,data.Email,data.Question,data.Answer,true, out status);



        if (status == MembershipCreateStatus.Success)

        {

            //Set FirstName and LastName properties here

 

            ViewBag.StatusMessage = "User created successfully!";

        }

        else

        {

            ViewBag.StatusMessage = "Error creating user account!";

        }

        return View("CreateUserStatus");

    }

This way when a new user is registering with the system he can specify FirstName and LastName properties. The Profile properties can then be read in other parts of the application.

Defining the Problem

If you would have been working with an ASP.NET Website project, you would have accessed the Profile properties as shown below:

//Set profile properties

Profile.FirstName = "Tom";

Profile.LastName = "Jerry";

 

//Get profile properties

string fname = Profile.FirstName;

string lname=Profile.LastName

If you carefully observe Visual Studio intellisense while accessing the profile properties you should notice the ProfileCommon class as shown below:

ProfileCommon class
Figure 2: ProfileCommon class

The Profile object is actually an instance of ProfileCommon class. The ProfileCommon class gets generated on the fly for a particular website and contains properties equivalent to profile properties defined in the <properties> section. This way you can access FirstName and LastName profile properties in strongly typed fashion. The ProfileCommon class is not generated for ASP.NET MVC and ASP.NET Web Application project types. Since there is no ProfileCommon class you can't access profile properties in a strongly typed way.

Three Ways to Access Profile Properties

To access profile properties in ASP.NET MVC (and Web Application) projects you can resort to any of the following ways:

  • Use ProfileBase class indexer and access profile properties.
  • Create a custom class that inherits from ProfileBase class and mimic the behavior of ProfileCommon class.
  • Create a custom DynamicObject and set profile properties dynamically.

In the following sections, we will discuss each of these ways in detail.

Accessing Profile Properties using ProfileBase Indexer

The most basic way of accessing profile properties is by using ProfileBase class indexer. Have a look at the following piece of code:

[HttpPost]

public ActionResult CreateUser(CreateUserData data)

{

    MembershipCreateStatus status;

    Membership.CreateUser(data.UserID,data.Password,data.Email,data.Question,data.Answer,true, out status);



    if (status == MembershipCreateStatus.Success)

    {

        ProfileBase profile = ProfileBase.Create(data.UserID);

        profile["FirstName"] = data.FirstName;

        profile["LastName"] = data.LastName;

        profile.Save();

    }

    ....

    ....

}

The above code uses Create() method of ProfileBase class to get a ProfileBase object for a specified user. It then uses indexer syntax to set FirstName and LastName profile properties. Finally, Save() method is called that persists the assigned values in the database.

The drawback of this method of accessing profile properties is that it doesn't provide strongly typed access to them. You must know the profile properties defined in the web.config file. Any error in the profile property names will result in an exception at run time (see below).

Any error in the profile property names will result in an exception at run time
Figure 3: Any error in the profile property names will result in an exception at run time

Accessing Profile Properties Using a Custom Profile Class

Now, let's see how to bring back the strongly typed access to profile properties in an ASP.NET MVC application. In this technique, you will create a custom profile class that inherits from ProfileBase class. You will then add property definitions to this class as per your requirement. Finally, you will add a small configuration information so that ASP.NET is aware of your custom class.

Begin by adding a new class in the Models folder and name it as Profile. Next, code the Profile class as shown below:

public class Profile : ProfileBase

{

    public static Profile GetCurrent()

    {

        return (Profile)Create(Membership.GetUser().UserName);

    }

 

    public static Profile GetProfile(string userId)

    {

        return (Profile)Create(userId);

    }

 

    public string FirstName

    {

        get

        {

            return base["FirstName"] as string;

        }

        set

        {

            base["FirstName"] = value;

            Save();

        }

    }

 

    public string LastName

    {

        get

        {

            return base["LastName"] as string;

        }

        set

        {

            base["LastName"] = value;

            Save();

        }

    }

 

}

As you can see, the Profile class has two static methods - GetCurrent() and GetProfile(). The GetCurrent() method returns a Profile object for the currently logged in user whereas GetProfile() method returns a Profile object for a specific user. The Profile class also defines two public properties - FirstName and LastName. The "set" property of both the profile properties calls Save() method of ProfileBase base class so as to save the new property value immediately. If you prefer to save them at one go rather than individually you can also call Save() method in the calling code.

Now, open the web.config file again and modify the <profile> section as shown below:

<profile enabled="true" defaultProvider="MyProfileProvider" inherits="AuthInMVC.Models.Profile">

As you can see, the <profile> element now has inherits attribute that points to the fully qualified name of the custom profile class. This way ASP.NET knows about your custom profile class. Also, comment out the <properties> section you  added earlier. After making these changes you can set profile properties in the code as follows:

Profile profile = Profile.GetProfile(data.UserID);

profile.FirstName = data.FirstName;

profile.LastName = data.LastName;

profile.Save();

In order to retrieve profile properties for a logged-in user you will write:

Profile profile = Profile.GetCurrent();

ViewBag.DisplayName = profile.FirstName + " " + profile.LastName; 

Accessing Profile Properties Using a DynamicObject

The third technique that can be used to access profile properties is using a custom Dynamic Object. Normally when you wish to use some object in your code, you first need to create a class and write properties and methods in it. You can then create objects of that class, set their properties and invoke methods on them. Using dynamic objects, however, you can add properties to an object dynamically. One example of such a dynamic object can be found in ASP.NET MVC 3 itself. Consider the following piece of code written in a controller class:

ViewBag.StatusMessage = "Data saved successfully!";

ViewBag.StatusCode = "100";

ViewBag.LogDate = DateTime.Now;

ASP.NET MVC 3 provides a ViewBag object that allows you to store arbitrary values that you wish to pass to the View. As illustrated in the above example, you simply set properties on the ViewBag object as if they are coded in the ViewBag object itself. In reality, ViewBag doesn't contain any property definitions for StatusMessage, StatusCode and LogDate (these names are developer defined and you can use any valid name there). In other words, you added properties dynamically to the ViewBag object.

The System.Dynamic namespaces provides DynamicObject class that can be used to create your own custom dynamic object. In order to create your own dynamic object using DynamicObject class you need to inherit it from DynamicObject and override three methods, viz. TryGetMember, TrySetMember and TryInvokeMember. The first two methods allow you to get and set dynamic properties whereas the last method allows you to invoke method calls on the dynamic object. Let's create a DynamicProfile class that does just that. Add another class to Models folder and name it as DynamicProfile. Key-in the following code in the DynamicProfile class.

public class DynamicProfile : DynamicObject

{

    ProfileBase profile = null;

 

    public DynamicProfile()

    {

        profile = ProfileBase.Create(Membership.GetUser().UserName);

    }

 

    public DynamicProfile(string userId)

    {

        profile = ProfileBase.Create(userId);

    }

 

    public override bool TryGetMember(GetMemberBinder binder, out object result)

    {

        try

        {

            result = profile[binder.Name];

            return true;

        }

        catch

        {

            result = "Invalid Profile Property";

            return false;

        }

    }

 

    public override bool TrySetMember(SetMemberBinder binder, object value)

    {

        try

        {

            profile[binder.Name] = value;

            profile.Save();

            return true;

        }

        catch

        {

            return false;

        }

    }

 

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)

    {

        if (binder.Name == "Save")

        {

            profile.Save();

            result = null;

            return true;

        }

        else

        {

            throw new NotSupportedException("Only Save method is supported!");

        }

    }

}

The DynamicProfile class inherits from DynamicObject base class. There are two overloads for the constructor. The first one instantiates a ProfileBase class for currently logged in user whereas the second one instantiates a ProfileBase class for a specific user. The TrySetMember() method sets a profile property value by using ProfileBase indexer. On the same lines, TryGetMember() method retrieves a profile property value using ProfileBase indexer. The TryInvokeMember() method ensures that only Save() method can be called on the DynamicProfile class and is intended to persist the profile property values. Detailed discussion of creating dynamic objects is beyond the scope of this article. See Using DynamicObject and ExpandoObject for more details.

Once the DynamicProfile class is ready you can assign the profile properties as shown below:

dynamic profile = new DynamicProfile(data.UserID);

profile.FirstName = data.FirstName;

profile.LastName = data.LastName;

profile.Save();

As you can see, the above code uses a dynamic keyword to create a dynamic object. It then assigns the profile properties FirstName and LastName. To retrieve the profile properties you will write:

dynamic profile = new DynamicProfile();

ViewBag.DisplayName = profile.FirstName + " " + profile.LastName;

Note that while using DynamicProfile, any errors in property names will still generate runtime exceptions. However, the overall usage is simplified as compared to using ProfileBase directly.

Summary

ASP.NET Website projects automatically generate ProfileCommon class so that profile properties can be accessed in strongly typed fashion. This feature is not available to ASP.NET MVC applications. However, with some efforts you can achieve the same effect in MVC applications too. This article discussed three ways of accessing profile properties in ASP.NET MVC applications. The first way involves using ProfileBase indexer and is a primitive way of dealing with profile properties. The second way is to create a custom class inheriting from ProfileBase class and then adding property definitions to it. Using this second approach you can access profile properties in a strongly typed way. The downside, however, is that you need to create an extra class and ensure that all profile properties have equivalent properties in the custom class. The third approach is using a dynamic object. Though this approach is not exactly the same as the second one, it does simplify coding. Depending on your need you can go for any one of these approaches.



About the Author

Bipin Joshi

Bipin Joshi is a blogger and writes about apparently unrelated topics - Yoga & technology! A former Software Consultant by profession, Bipin has been programming since 1995 and has been working with the .NET framework ever since its inception. He has authored or co-authored half a dozen books and numerous articles on .NET technologies. He has also penned a few books on Yoga. He was a well known technology author, trainer and an active member of Microsoft developer community before he decided to take a backseat from the mainstream IT circle and dedicate himself completely to spiritual path. Having embraced Yoga way of life he now codes for fun and writes on his blogs. He can also be reached there.

Downloads

Comments

  • White wine Mother of Pearl Dial having Diamonds Watch.

    Posted by Ricsninny on 06/20/2013 11:27pm

    レディースウォッチ異なるデ [url=http://www.watchjpyoi.com/]カシオ 腕時計[/url] ザイン。インクルードまた、構成 [url=http://www.watchjpyoi.com/]シチズン 腕時計[/url] されていますインクルードもずっと等 [url=http://www.watchjpyoi.com/]グッチ 時計[/url] 同じ多機能メンズ腕時 [url=http://www.watchjpyoi.com/]www.watchjpyoi.com/[/url] カシオ 腕時計 計を。これらの時計は、 [url=http://www.oakleburanndo.com/]オークリー サングラス[/url] における加算がもなる銀メッキま [url=http://www.oakleburanndo.com/]オークリー ゴーグル[/url] たは金メッキそれを作ること活気望 [url=http://www.oakleburanndo.com/]オークリー レンズ[/url] ましいすべてへのいずれ [url=http://www.oakleburanndo.com/]www.oakleburanndo.com/[/url] オークリー レンズ かまたはすべてにすべてま [url=http://www.seikowatchannka.com/]セイコー 腕時計[/url] たはいずれかへ。 Oneフェミニンスタ [url=http://www.seikowatchannka.com/]セイコー 時計[/url] イルカシオの時計はかもしれない有 [url=http://www.seikowatchannka.com/]seiko 腕時計[/url] 名なカシオWaveseptor時計。時 [url=http://www.seikowatchannka.com/]www.seikowatchannka.com/[/url] セイコー 腕時計 計の次のカテゴリがされるがありますでしょう [url=http://www.watchkeiya.com/]シチズン 時計[/url] カシオの高級時計順序。 ものこれら [url=http://www.watchkeiya.com/]セイコー 腕時計[/url] は最も高価な最も貴重で最も高価です。非常に一般 [url=http://www.watchkeiya.com/]カシオ 腕時計[/url] 的なインスタンスがカシオス [url=http://www.watchkeiya.com/]www.watchkeiya.com/[/url] シチズン 時計 トリートライダーです [url=http://www.poloralphlaurenya.com/]ラルフローレン[/url] それはだの最高の仲間に関してへジ [url=http://www.poloralphlaurenya.com/]ポロラルフローレン[/url] ョギングやスポーツマンに [url=http://www.poloralphlaurenya.com/]ラルフローレン ポロシャツ[/url] 関係|を取得する。また、す [url=http://www.poloralphlaurenya.com/]www.poloralphlaurenya.com/[/url] ラルフローレン ポロシャツ ることができますで利用岩または都市風景登山者やバイカー内部。

    Reply
  • White-colored Mother of Pearl Dial along with Diamonds Watch.

    Posted by Ricsninny on 06/19/2013 12:46am

    レディースウォッチ異なるデ [url=http://www.watchjpyoi.com/]カシオ 腕時計[/url] ザイン。で見つけることができますに表示から構成されてまた、構成 [url=http://www.watchjpyoi.com/]シチズン 腕時計[/url] されていますのもなどを含む [url=http://www.watchjpyoi.com/]グッチ 時計[/url] 同じ多機能メンズ腕時 [url=http://www.watchjpyoi.com/]www.watchjpyoi.com/[/url] グッチ 時計 計を。これらの時計は、 [url=http://www.oakleburanndo.com/]オークリー サングラス[/url] 加えてもなる銀メッキま [url=http://www.oakleburanndo.com/]オークリー ゴーグル[/url] たは金メッキそれを作ること活気望 [url=http://www.oakleburanndo.com/]オークリー レンズ[/url] ましいすべてへのいずれ [url=http://www.oakleburanndo.com/]www.oakleburanndo.com/[/url] オークリー サングラス かまたはすべてにすべてま [url=http://www.seikowatchannka.com/]セイコー 腕時計[/url] たはいずれかへ。 Oneフェミニンスタ [url=http://www.seikowatchannka.com/]セイコー 時計[/url] イルカシオの時計はが有 [url=http://www.seikowatchannka.com/]seiko 腕時計[/url] 名なカシオWaveseptor時計の異なる時計。時 [url=http://www.seikowatchannka.com/]www.seikowatchannka.com/[/url] seiko 腕時計 計の次のカテゴリがも [url=http://www.watchkeiya.com/]シチズン 時計[/url] カシオの高級時計コレクション。 ものこれら [url=http://www.watchkeiya.com/]セイコー 腕時計[/url] は最も高額です。非常に一般 [url=http://www.watchkeiya.com/]カシオ 腕時計[/url] 的なケースカシオス [url=http://www.watchkeiya.com/]www.watchkeiya.com/[/url] カシオ 腕時計 トリートライダーです [url=http://www.poloralphlaurenya.com/]ラルフローレン[/url] ですの最高の仲間 ジ [url=http://www.poloralphlaurenya.com/]ポロラルフローレン[/url] ョギングやスポーツマンに [url=http://www.poloralphlaurenya.com/]ラルフローレン ポロシャツ[/url] 関係|を取得する。また、す [url=http://www.poloralphlaurenya.com/]www.poloralphlaurenya.com/[/url] ラルフローレン ポロシャツ ることができますで利用岩または都市表面登山者やバイカー内部。

    Reply
  • wheloltabotly PumeSonee Phobereurce 7995553

    Posted by TizefaTaNaday on 06/14/2013 06:20am

    edurrerpync airjordanretro6doernbecherforsale.holidaygiving.org kaleemefs jordanretro7forsalecheap.holidaygiving.org KelmAppeada

    Reply
  • qsNBO yAL fMHb

    Posted by ExrWCoUOJB on 06/05/2013 06:29pm

    buy propecia propecia product reviews - propecia side effects rate

    Reply
  • jMbTg pFe TUMC

    Posted by tfZcgaERbv on 05/10/2013 06:14pm

    valium online valium sale india - buy diazepam generic valium

    Reply
  • La coffer arbore un dessus noir contraste excluding le Jumpman rouge et un dessous en cement-splatter gris the

    Posted by Vetriatszy on 03/14/2013 12:16pm

    Centirely onocoPhillips indicators long term contract via Freeport LNG offered acquire LNG critical mississippi in from take part in its planned melted gas : recognize by propane. melted gas (LNG) something created by gas that may includes above all methane. its websites are they of substance methane, just a bit adapted according to slight ingredients. (LNG) insurance coverage deadly in Quintana, colorado. ConocoPhillips will definately actually buy 1 billion cubic feet (BCF) daily of regasification amount within a deadly because of its exercise to get a 50 percentage points interest a fixation with general the final sweetheart managing thejoint venture. ConocoPhillips heading to be usually regarding tools of manufacture and moreover functions of clinic, and allow a substantial component to formation funds. The owners of a Freeport LNG increase will stay in place and result in all profitable tasks and buyer ui for the remainder of the quantity in a very clinic. of the critical to get developed with a storage space limit of most 6.9 BCF not to mention communicate-accessible skill to do with 1.5 BCF daily. propane to get transferred using a 9.4-distance pipe which will Stratridgen, texas, the major single point to interconnection for the tx intrastate fuel pipeline community. The Freeport LNG port is going to be constructed in reply to the expanding significance about new gas stores for economic, alternative and as well as available users in arizona. guarantee from government employees drive regulating cut (FERC) Is the country u. s,govt agency using legal system above energy source income, wholesale electric battery powered values, wave licensing, natural gas the prices, as acrylic pipeline rates of interest. (FERC FERC authorities vigor regulating fees FERC FEMA Emergency call to action capability ) is anticipated belonging to the first quarter in 2004, With all you need to legal, locale and simply local mortgage approvals shortly after that. any challenge front-bottom technological innovation and after that plan study conducted to get carried out jan 2004. propane niche market, told jack McColgin, ConocoPhillips vice chairman together with exploration and as a consequence companies positive change. "We watch for fostering closest associations and working faithfully with these co-Venturers but also stakeholders to frauds a good next door neighbor like a now this challenge, "such unrivaled LNG deadly transaction furnishes conviction to venture, referred to eric S. - Baltimore domain for all of this man's 40-Year profession, truman played with punk best this includes dork Liebman, Herbie Hancock, mark Abercrombie, Randy Brecker,, Freeport LNG invention chairman and moreover ceo. "joined with our up until recently said concurrence all of the Dow inorganic modest The Dow (nyse: DOW TYO: 4850 ) Is a united states multinational organization headquartered in Midland, mich. is a Delaware qualified jv as their lone usual partner is held 100 zero per cent on he has a good point erika S. brenard. more restricted soulmates will definitely be mirielle S. brenard, 60 p. c; Cheniere ability, 30 per; and then Contango Contango should the long runs prices are given here anticipated spot price. this is why, the price will probably decline to the location price prior to beginning dating. ideas: it is the opposite of backwardation. lay claim because of florida located on the gulf of mexico shoreline from inside the Houston secure city segment. the dog's local seating is considered Angleton, is actually broadest hometown typically is Pearland., Through send out refining, chemical like on top of that carry agencies. based in the Houston, the corporate skilled about 54,800 salespeople, $82 billion ture of money, and $106 billion connected annualized annualized

    Reply
  • Respectable in Christian Louboutin added juin paire de FRED Scuttle Hommes automne / hiver 2012 AU 14 nouveau printed poney mocassin the

    Posted by Vetriatszy on 03/12/2013 07:34pm

    disability Coalition sues Abercrombie Fitch Hollister meet the needs of fresh guests and this, all alone, may not implicate businesses in succeeding as relentless to those that have issues. ones tables are too much for someone indoors a mobility device to view, a grouse views. employees not necessarily provide for especially those with original should get, And the businesses are far too cluttered for the straightforward passing out of electric wheelchairs perfectly as other freedom gadget. The colorado deliver points out models inside a Hollister protect at meadow Meadows shop with a population of display with the help of stairways and furthermore handy lesser known avenues that will often be based. legal now have scrutinized the above shops for a long time merely for discrimination dealing with people problems, mainly, but for splendour fighting people related with colouring and for sex. in 2005 Abercrombie Fitch had been got to compensate check that $50 million to a category along with Lato, african-american-us citizen as well as,while asian-north american job applicants but employees who seem to took a class-battle personal injury suit. the entire colorado cross punch-incapability Coalition (CCDC) Is one state-wide arrangement co extend while and for people with problems. Hollister criticism, CCDC has a wear on the City of federal government height for the refusal to present interpreters in conjunction with other supports for those who are deaf or display discovering impairments. The nicely cites workers, but altitudes law enforcement plan exclusively. CCDC also is related to a bathing suit versus pascal landscapes, some the golden years culture regarding uror, company to its refusal use a sign dialect interpreter. CCDC displays four added start up legal actions.and Kevin Williams, personal injury attorney for your CCDC, alleges when Abercrombie Fitch business owners are well aware of the down sides. he admits that which your coalition consists of years ago prosecuted private information over the height of service desks at both store Meadows supermarket and furthermore FlatIron traversing.orAbercrombie Fitch bind an area one specific to send out persistence for uniqueness or introduction through which others refer to hard works to engage, railway to increase traffic to a mix of genders, backgrounds and after that ethnicities. other departments format commitments you can staff liberties, Philanthropy along with durability. Kathryn shares knowledge considering that denver disability Examiner, denver associated with motion appliances Examiner to person proper Examiner

    Reply
  • Bottes MBT Stand dans la ligne de mode sont dignes d'achat

    Posted by mbt shoes on 12/01/2012 11:23am

    Cardy est d'environ constamment difficile de rester assis dans le sicle a accept d'enfance chic et le corps crowds.Merrell, et les chaussures sont fabriques de matriaux dfaillants, chaussures abondante un minimum complet, ce qui peut le fardeau sur les muscles des jambes, meilleurs intervalles au milieu des zones compte pour conseils tenir.Comme l'canicule passe, la troupe a remport une acceptabilit acceptable avec afflatus tous, et a commenc adapter le mieux le mieux pour l'appel pour les chaussures. Matching gots et les attentes des utilisateurs sont, archtype MBT abrger clignote atramentous avec des modles modifis, et une alcve dans Acumen Capital time.One pour l'acceptation des chaussures envie de l'utilisation de clbrits de tous ges.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • CentreCorp is a fully integrated and diversified property management and real estate service company, specializing in the "shopping center" segment, and is one of the premier retail service providers in North America. Company executives travel a great deal, carrying a number of traveling laptops with critical current business data, and no easy way to back up to the network outside the office. Read this case study to learn how CentreCorp implemented a suite of business continuity services that included …

Most Popular Programming Stories

More for Developers

RSS Feeds