WCF Data Services & OData Protocol

February 11, 2010 15:03 by jasonp

Well, you've heard of Web Services and software as a service etcetera. Well, WCF Data Services (formerly known as ADO.NET Data Services) is the whole new notion of exposing your data through something we call the Data Service.

Data today tends to exist in horizontal or vertical silos: it can be shared within a particular environment but often becomes difficult (if not painful) to use beyond its original intent.  As systems continue to become more interconnected, the need to reuse information also grows and the value of any given data becomes greater the more it can be shared and accessed by other systems. The “silo effect”, on the other hand, limits that access and the data's value.

The Open Data Protocol, referred to as OData, is a new data-sharing standard that breaks down silos and fosters an interoperative ecosystem for data consumers (clients) and producers (services) that is far more powerful than currently possible. It enables more applications to make sense of a broader set of data, and helps every data service and client add value to the whole ecosystem. WCF Data Services (previously known as ADO.NET Data Services), then, was the first Microsoft technology to support the Open Data Protocol in Visual Studio 2008 SP1. It provides developers with client libraries for .NET, Silverlight, AJAX, PHP and Java. Microsoft now also supports OData in SQL Server 2008 R2, Windows Azure Storage, Excel 2010 (through PowerPivot), and SharePoint 2010. Many other other applications in the works

In addition to client libraries that simplify working with OData, the Data Services framework builds on the general WCF capabilities to provide a near-turnkey solution for creating OData services for the web. Data Services enable you to expose data models to the Web in a RESTful way, with rich built-in data access capabilities such as flexible querying, paging, and association traversal.

The Data Services framework facilitates the creation of flexible data services that are naturally integrated with the web. WCF Data Services use URIs to point to pieces of data and use simple, well-known formats to represent that data, such as JSON and ATOM (XML-based feed format). This results in the data service being surfaced as a REST-style resource collection that is addressable with URIs and with which agents can interact using standard HTTP verbs such as GET, POST, PUT or DELETE.

In order for the system to understand and leverage semantics over the data that it is surfacing, Data Services models exposed data exposed using the Entity Data Model (EDM), an Entity-Relationship derivative. This organizes the data in the form of instances of "entity types" (or "entities") and the associations between them.

For relational data, Data Services supports exposing an EDM model created using the ADO.NET Entity Framework. It also includes a provider model that enables any data source (including non-relational sources) to be represented using the EDM and exposed as a data service.


Photo360 Challenge

February 9, 2010 22:32 by yanglin

 

 

Hey guys! We updated the contest page, register and find out more here


Silverlight Singapore Facebook Group

January 20, 2010 21:44 by eugene

Silverlight Trainer and former MVP Dewi Maya started a Silverlight Singapore group in Facebook. If you are interested in learning, collaborating and exploring the features and capabilities of Silverlight, the FB group is a good place to start. I've been seeing a lot of samples and tutorials being posted there as well.

On a sidenote, we just finished our January Silverlight Training. We will be seeing a lot more updates on Silverlight come March so be sure to stay tuned. MIX10, Microsoft's designer conference would have a lot of news for sure and Silverlight will be one of them. I'm guessing Silverlight 4. If you want to know more about MIX, visit their site here http://live.visitmix.com/ You can also watch the previous MIX sessions. Very very interesting talks for designers and developers.

Silverlight Singapore Facebook Group

http://www.facebook.com/#/group.php?gid=292655079571&ref=ts


Microsoft BizSpark - Business Enablement Program

December 30, 2009 19:37 by eugene

My colleague, Chris Ismael, wrote a great blog post on one of the programs that are offered as part of the BizSpark program here in Singapore. I was personally there and I greatly appreciated the lessons taught. It was very different from the technical hands on labs or technical updates that Microsoft usually does.

Check out his awesome blog here http://blogs.msdn.com/chism

If you are interested in joining the BizSpark program, you can email me or email him directly for more information.

Happy Holidays guys and keep on rocking!

 


Deploying PHP + MySQL + Wordpress on Azure

December 18, 2009 19:31 by jasonp

In this entry, I will talk about the steps needed to get PHP + MySQL + Wordpress running on Azure. I will be using Wordpress here as a sample PHP application but once you know this, you will be able to deploy any PHP application on Windows Azure.

 

Pre-requisites:

1. PHP Binaries for IIS (http://windows.php.net/)

2. MySQL Binaries (Without Installer) (http://dev.mysql.com/downloads/mysql/5.1.html )

2. MySQL PHP Solution Accelerator (http://code.msdn.microsoft.com/winazuremysqlphp )

3. VS2008 SP1/VS2010 Beta 2 w/ Windows Azure SDK

4. Wordpress (Or any PHP Application)

5. “The Lazy Man Hello Cloud PHP” ( http://innovativesingapore.com/post/The-Lazy-Mane28099s-e2809cPHP-Hello-Cloude2809d.aspx ) [Optional but Reccomended]

Phase 1 – Setup

1. Install the MySQL PHP Solution Accelerator         

2. Extract the PHP binaries for IIS to the “php” folder in the PhpMyAdminWebRole directory. E.g. “C:\Samples\AzureMySQLPHP_x86\PhpMyAdminWebRole\php”

3. Extract the Wordpress files to the “wordpress” folder in the PhpMyAdminWebRole directory. E.g. “C:\Samples\AzureMySQLPHP_x86\PhpMyAdminWebRole\wordpress”

4. Extract the MySQL Binaries to the “mysql” folder in the MySQL_WorkerRole directory. E.g. “C:\Samples\AzureMySQLPHP_x86\MySQL_WorkerRole”

Phase 2 – Windows Azure Cloud Service

5. Create a new “Windows Azure Cloud Service” solution in Visual Studio.

6. Add an existing project, “PhpMyAdminWebRole” (From the Solution Accelerator), to the solution you created.

7. Add another existing project, “MySQL_WorkerRole” (Also from the Solution Accelerator,), to the solution.

8. Right click on “Roles” (Found in your “Windows Azure Cloud Service” project) and select “Add-> Web Role Project in solution” and select the project you added in your solution previously.

9. Repeat step 8, but this time, choose “Add -> Worker Role Project in solution” and select the “MySQL_WorkerRole” you added previously.

Phase 3 – Configuring MySQL_WorkerRole

*For learning purposes we shall not touch on the advance features of the MySQL_WorkerRole in the Solution Accelerator. If you do want to do more with it, please watch this video: http://microsoftpdc.com/Sessions/SVC51 .
For now, we are going to configure the worker role to have only 1 instance.

10. Open up the settings for “MySQL_WorkerRole” (Found in the Roles folder at your “Windows Azure Cloud Service” project) and change the following configurations:

Configuration Section
Instance Count: 1

Settings Section [Name, Type, Value]
TableStorageEndpoint, String, http://table.core.windows.net

BlobStorageEndpoint, String, http://blob.core.windows.net

DataConnectionString, ConnectionString, UseDevelopmentStorage=true

DiagnosticsConnectionString, ConnectionString, UseDevelopmentStorage=true

ContainerName, String, mysqlphp11

FullBackupHour, String, 06:00

IncrementalBackupDuration, String, 10

RecycleThreadSleepTime, String, 300

EnableWindowsAzureDrive, String, False

EnableBackup, String, False

*Note, we will be using the Dev Fabric Storage in this walkthrough, feel free to use your cloud storage if any.


Endpoints (Name, Type, Protocol)

PeerEndpointIn, Internal, tcp

MasterElectionService, Internal, tcp

MySQL, Internal, tcp

InstanceManagerEndpontIn, Internal, tcp


Local Storage

MySQLStorage, 200MB

MySQLDatastore, 1024MB

BlobBackup, 500MB

 

Next up, we want to edit the behavior of the worker role such that when the worker role starts, it will update the PHP ini (configuration) file so that our PHP web role will know where is the MySQL database located in the cloud.

11. Open up MySQLAccess.cs in “MySQL_WorkerRole” project and make the following changes:

In the internal class “MySQLClient” add a string constant – relative path to your php ini file.

Code:
 
private const string REL_PATH_TO_PHP_INI = "./../../PhpMyAdminWebRole/approot/php/php.ini";

 

Next find the line “string masterHost = instance.IPEndpoint.Address.ToString();

“ and add the following after the line:

 

Code:

//Set php ini so PHP knows where is the host and port of the MySQL endpoint

FileStream fs = File.OpenRead(REL_PATH_TO_PHP_INI);

StreamReader reader = new StreamReader(fs);

//Read all text in INI File

string php_ini = reader.ReadToEnd();

 

//Closing resources

reader.Close();

fs.Close();

 

//Add in details (Host IP Address and Port)

php_ini = php_ini.Replace("mysql.default_port =", "mysql.default_port = " + port);

php_ini = php_ini.Replace("mysql.default_host =", "mysql.default_host = " + masterHost);

File.WriteAllText(REL_PATH_TO_PHP_INI, php_ini);               

string iniFile = Path.Combine(baseDir, "my.ini");

File.Copy("my.ini", iniFile, true);

 

 

[NEW UPDATE!]

 

I have changed the logic of the codes to use Environment Variables instead of updating the PHP INI file on runtime. Please make sure your function "public bool Start(int id)" looks something like the one below. (: The code is now easier to understand and shorter.

 

public bool Start(int id)

        {

            try

            {

                string baseDir = RoleEnvironment.GetLocalResource("MySQLStorage").RootPath.Replace('\\', '/');

                string dataDir = RoleEnvironment.GetLocalResource("MySQLDatastore").RootPath.Replace('\\', '/');

                string blobDir = RoleEnvironment.GetLocalResource("BlobBackup").RootPath.Replace('\\', '/');

                LogError("MySql Base directory: {0}", baseDir);

                LogError("MySql Data directory: {0}", dataDir);

 

                string command = Path.Combine(baseDir, @"bin\mysqld.exe");

                SetupBlobBackup(blobDir);

                if (!File.Exists(command))

                {

                    SetupAzureMySql(baseDir);

                    SetupAzureMySqlDataDir(dataDir);

                }

                MySqlConnection rootConn = GetConnection(_endpointName);

                if (IsRunning(_endpointName))

                {

                    int currentId = GetMySqlServerId();

                    if (currentId == id)

                    {

                        return true;

                    }

                    command = Path.Combine(baseDir, @"bin\mysqladmin.exe");

                    Process.Start(command, "-u root shutdown");

                }

              

                RoleInstanceEndpoint instance;

 

                //Get the "MySQL" instance

                instance = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["MySQL"];

 

                //Get the port of the instance

                string port = instance.IPEndpoint.Port.ToString();

                Environment.SetEnvironmentVariable("MasterPort", port, EnvironmentVariableTarget.Process);

                //Get the IP address of the instance

                string masterHost = instance.IPEndpoint.Address.ToString();

 

                Environment.SetEnvironmentVariable("MasterHost", masterHost, EnvironmentVariableTarget.Process);

 

 

 

                string iniFile = Path.Combine(baseDir, "my.ini");

                //update the my.ini file with mysql server details

                UpdateMyIni(iniFile, baseDir, dataDir, port, id.ToString());

                ProcessStartInfo startInfo = new ProcessStartInfo(command);

                startInfo.RedirectStandardOutput = true;

                startInfo.WorkingDirectory = baseDir;

                startInfo.UseShellExecute = false;

                startInfo.CreateNoWindow = false;

                startInfo.Arguments = "--console";

                Process driver = new Process();

                driver.StartInfo = startInfo;

                driver.Start();

 

 

                StreamReader sr = driver.StandardOutput;

                string output = sr.ReadToEnd();

                while (!IsRunning(_endpointName))

                {

                    Thread.Sleep(TimeSpan.FromSeconds(10));

                }

            }

            catch (Exception ex)

            {

                LogError("Error in MySqlAccess start(): {0}", ex.Message + ex.StackTrace);

                return false;

            }

            return true;

        }

 

Phase 4 – Configuring Wordpress

12. Copy “wp-config-sample.php” in the “wordpress” folder to “wp-config.php” then open up “wp-config.php”

13. You may want to look at http://codex.wordpress.org/Editing_wp-config.php to know more about what each setting does.

 

Under the MySQL hostname section, set it to be “define('DB_HOST', ini_get("mysql.default_host").':'.ini_get("mysql.default_port"));” , without the quotes of course ;)

[NEW UPDATE!]

Under the MySQL hostname section, set it to be “define('DB_HOST', getenv("MasterHost").':'.getenv("MasterPort"));” , without the quotes of course ;)

 

For the rest of the settings, configure it as per normal (refer to:  http://codex.wordpress.org/Editing_wp-config.php)

 

Phase 5 – Deploying

14. We will use the Dev Fabric for now. Hit F5 and wait for all your instances to run.

Important : For those who want to deploy on the cloud,

 

Phase 6 – Database Setup + Testing

15. Navigate to your PhpMyAdmin site. (If you didn’t change any settings, it should be at http://localhost:81/PhpMyAdmin/index.php )

16. Login as root with no password.

17. Create a new database (the name for the database you defined when setting up wp-config.php, lets say “wordpressdb”) called “wordpressdb”.

18. Create new user with the credentials you set in “wp-config.php” previously and give the necessary rights. Remove the root users’ privileges after you created the new user (security concerns here.)

19. You can now proceed to your WordPress app to test! (Default: http://localhost:81/wordpress/index.php)
WordPress will detect whether the app have been set up or not and prompt you accordingly. Enjoy your new PHP Application using MySQL on Windows Azure Cloud!

If you have any queries, feel free to email me at v-japoh@microsoft.com or MSN me @ Jason_scorpio@hotmail.com . ;)

 

You just need to change the storage settings to point to your Windows Azure storage and it will work. Publish the project as per normal and deploy as per normal.

 

---

 

Settings for MySQL:

 

DataConnectionString, ConnectionString, UseDevelopmentStorage=true

DiagnosticsConnectionString, ConnectionString, UseDevelopmentStorage=true

 

Change the above to use Windows Azure Storage.

 

Common Problems Encountered & Solutions

Here I have included some of the problems others faced for the benefit of those who might meet the same problems (:

(1) phpmyadmin folder is empty

     - Could not find file 'C:\Samples\AzureMySQLPHP_x86\PhpMyAdminWebRole\PHPMyAdmin\browse_foreigners.php';

     - Could not find file 'C:\Samples\AzureMySQLPHP_x86\PhpMyAdminWebRole\PHPMyAdmin\bs_change_mime_type.php';    

- Could not find file 'C:\Samples\AzureMySQLPHP_x86\PhpMyAdminWebRole\PHPMyAdmin\bs_disp_as_mime_type.php'.

     Solution: I downloaded the phpmyadmin and paste the folder into the phpmyadmin folder in Accelerator.

 

(2) Cannot load mysql extension.

     Solution: In php.ini, uncomment extension=php_mysql.dll, extension=php_mbstring.dll.

 

(3) HTTP Error 500.0 - Internal Server Error

     Solution: In php.ini, locate the extension_dir setting. Change the value to “./ext” and locate the cgi.force_redirect setting and remove the comment and set the value to 0. Set cgi.fix_pathinfo and fastcgi.impersonate to 1.

 (4)Missing Dlls

     Solution: If the dlls are not found inside the windows php distribution binaries, the dlls belongs to optional add-ons. You can simply delete the missing dll references from the project.

 


Windows Live Messenger Theme Pack

December 14, 2009 21:49 by jasonp

Here are a list of things which you might not know about when creating a Windows Live Messenger Theme Pack:

Known Issues

  • COM Object "MessengerContentInstallerLibrary" does not works on 64-bit machines.
    Seems like you need to target the build to only x86 machines (32-bt machines) that will force the assembly to run in WOW64 instead of 64 bit
  • You need to be signed in to Windows Live Messenger to be able to install a theme pack.
  • A theme pack must be served from a HTTP Server.
  • Therefore, you must be connected to the internet to install a theme pack. (There is a workaround for this, to simulate a http server using Sockets, which I didn't have any success in it.)

 

How to handle Installer events

To notify your application after the installer has finished installing the theme pack use the following event handler, DMessengerContentEvents_OnContentInstalledEventHandler

Example:

mci = new MessengerContentInstaller();

MessengerContentInstaller

 

 

 

mci.OnContentInstalled +=new DMessengerContentEvents_OnContentInstalledEventHandler(mco_OnContentInstalled); } 

private void mco_OnContentInstalled(int lhrResult)

 

 

 

 

 

To identify whether the installation has an error while installing, check the "int lhrResult" param. If the value is = 0, the installation completed successfully. Other than that, the installation has failed and you need to let the user retry the installation.

A theme pack (winter themed pack) which I built is available here: http://jasoncloud.cloudapp.net/ .

{

...

 


The Lazy Man’s “PHP Hello Cloud”

December 11, 2009 02:48 by jasonp

Due to the popular demand on how to actually host a PHP application on Windows Azure, this post teaches you the easiest way to deploy your PHP applications on the Cloud with the least effort and there is no need to use Windows Azure

Resources Needed:

1. PHP Binaries for IIS (http://windows.php.net/)
2. MySQL PHP Solution Accelerator (
http://code.msdn.microsoft.com/winazuremysqlphp)
3. VS2008 SP1/VS2010 Beta 2 w/ Windows Azure SDK

Steps:

1. Install the MySQL PHP Solution Accelerator.

2. Extract the PHP binaries for IIS to the “php” folder in the PhpMyAdminWebRole directory. E.g. “C:\Samples\AzureMySQLPHP_x86\PhpMyAdminWebRole\php”

3. Create a new “Windows Azure Cloud Service” solution in Visual Studio.

4. Add an existing project, “PhpMyAdminWebRole” (From the Solution Accelerator), to the solution you created.

5. Right click on “Roles” and select “Add-> Web Role Project in solution” and select the project you added in your solution previously.

6. Add a new text file in “PhpMyAdminWebRole” and name it “index.php”. The contents of the file is “ <?php echo ‘Hello Cloud’; ?> “

7(Optional). Open Web.config and replace “ <add value="Admin.aspx"/>” to “ <add value="index.php"/>

 

 

And you are all set! Hit F5 in your Visual Studio to see your work in action on the Development Fabric.


MSDN and Technet Singapore

December 11, 2009 00:10 by eugene

If you've been developing or using Microsoft technology, for sure, one way or another you have used either MSDN or Technet as one of your resources. Microsoft has done great lengths in providing comprehensive documentation to developers and IT Pros. Just recently, the MSDN and Technet pages have been revamped to cater more to local countries. This means that you'll have the best resources from MSDN and Technet as well as relevant local content such as events, blogs, communities and overall goodness from the Microsoft community. Take advantage of this new resource to connect and learn by visiting the links below.