One of my side projects was to get an MVC3 application that uses the Razor View Engine and Membership hosted on EC2 running Linux. I found some amazingly helpful resources along the way – particularly from Nathan Bridgewater at Integrated Web Systems.
Step one of the project is to get an EC2 instance prepped and ready. Basically I followed the cookbook instructions on Bridgewater’s site - Get Started with Amazon EC2, Run Your .Net MVC3 (RAZOR) Site in the Clould with Linux Mono.
The exact commands I used:
Create new AMI ID ami-ccf405a5 and associate elastic IP (xx.xx.xx.xx) sudo apt-get update &;& sudo apt-get dist-upgrade –y wget http://badgerports.org/directhex.ppa.asc sudo apt-key add directhex.ppa.asc sudo apt-get install python-software-properties sudo add-apt-repository 'deb http://ppa.launchpad.net/directhex/ppa/ubuntu lucid main' sudo apt-get update sudo apt-get install mono-apache-server4 mono-devel libapache2-mod-mono cd /srv sudo mkdir www; cd www sudo mkdir default sudo chown www-data:www-data default sudo chmod 755 default cd /etc/apache2/sites-available/ sudo vi mono-default (see mono-default, change IP address) cd /etc/apache2/sites-enabled sudo rm 000-default sudo ln -s /etc/apache2/sites-available/mono-default 000-mono sudo mv /var/www/index.html /srv/www/default sudo vi /srv/www/default/index.html sudo apt-get install apache2 sudo service apache2 restart Test in a browser via IP address (you should see the default apache page)
My mono default:
# xx.xx.xx.xx is my Elastic IP address
ServerName xx.xx.xx.xx
ServerAdmin myemail@domain.com
DocumentRoot /srv/www/default
MonoServerPath xx.xx.xx.xx "/usr/bin/mod-mono-server4"
MonoDebug xx.xx.xx.xx true
MonoSetEnv xx.xx.xx.xx MONO_IOMAP=all
MonoApplications xx.xx.xx.xx "/:/srv/www/default"
Allow from all
Order allow,deny
MonoSetServerAlias xx.xx.xx.xx
SetHandler mono
SetOutputFilter DEFLATE
SetEnvIfNoCase Request_URI "\.(?:gif|jpe?g|png)$" no-gzip dont-vary
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/javascript
Step two is to test mono with a simple Asp.net page. Put this file into /srv/www/default. Edit with sudo and view via browser at http://xx.xx.xx.xx/test.aspx.
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>ASP.Net Test page</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script runat="server">
private void Page_Load(Object sender, EventArgs e)
{
lblTest.Text = "This is a successful test.";
}
</script>
</head>
<body>
<h1>
This is a test page</h1>
<asp:Label runat="server" ID="lblTest"></asp:Label>
</body>
</html>
sudo apt-get install mysql-server sudo apt-get install libmysql6.1-cil CREATE DATABASE sample; USE sample; CREATE TABLE test (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(25)); INSERT INTO sample.test VALUES (null, 'Lucy'); INSERT INTO sample.test VALUES (null, 'Ivan'); INSERT INTO sample.test VALUES (null, 'Nicole'); INSERT INTO sample.test VALUES (null, 'Ursula'); INSERT INTO sample.test VALUES (null, 'Xavier'); CREATE USER 'testuser'@'localhost' IDENTIFIED BY 'somepassword'; GRANT ALL PRIVILEGES ON sample.* TO 'testuser'@'localhost'; FLUSH PRIVILEGES;
Put this file into /srv/www/default. Edit with sudo and view via browser at
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="MySql.Data.MySqlClient" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>ASP and MySQL Test Page</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script runat="server">
private void Page_Load(Object sender, EventArgs e)
{
string connectionString = "Server=127.0.0.1;Database=sample;User ID=testuser;Password=somepassword;Pooling=false;";
MySqlConnection dbcon = new MySqlConnection(connectionString);
dbcon.Open();
MySqlDataAdapter adapter = new MySqlDataAdapter("SELECT * FROM test", dbcon);
DataSet ds = new DataSet();
adapter.Fill(ds, "result");
dbcon.Close();
dbcon = null;
SampleControl.DataSource = ds.Tables["result"];
SampleControl.DataBind();
}
</script>
</head>
<body>
<h1>Testing Sample Database</h1>
<asp:DataGrid runat="server" ID="SampleControl" />
</body>
</html>
Step four is to get the simplest possible MVC3 Razor application functioning on Ubuntu / EC2. Again Bridgewater has a more detailed explanation of what to do at his website linked here.
- Go into Visual Studio 2010 and create a new project MV3 / Razor project making no changes to the default project template.
- Build it and locally.
- Ensure that these references are set to “copy local”: System.Web.Mvc, System.Web.Helpers, and System.Web.Routing
- Copy System.Web.Razor, System.Web.WebPages, System.Web.WebPages.Razor, System.Web.WebPages.Deployment into your application’s bin directory. You will find these files in in C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies
- Publish the application to a scratch directory
- Copy the published application to your EC2 machine. I used git bash to tar (tarr –zcvf aws.tar.gz *) the files as Bridgewater recommends but could not get scp to work so I ftp’d the file over.
- On the EC2 machine cd /srv/www/default; sudo mv /home/ubuntu/aws.tar.gz; sudo tar –zxvf *.gz; sudo chown –R www-data;www-data *; sudo chmod 755 *; sudo service restart apache2 restart
- Confirm working from browser by checking default IP address http://xx.xx.xxx
- NB: I had to hit refresh several times before the application would work.
Step five is to use implement membership using MySQL.
- On your Windows machine. Edit the default controller and decorate it with the [Authorize] attribute.
- Edit your web.config shown below. This is where it can get hairy. If you want to run this locally on Windows you need to install the MySQL connector for .Net and Mono http://dev.mysql.com/downloads/connector/net/. Make sure that you reference system.web. On Ubuntu the application uses system.data. The trick is to add them both so you can run the same code on Ubuntu and Windows. Also notice that I’ve made database password clear text. As Nathan notes this is not a good practice.
- On the Ubuntu machine Go into MySQL and create a database called membership.
- Deploy the application to EC2 and test the application using step 4.
<?xml version="1.0"?> <!-- For more information on how to configure your ASP.NET application, please visit http://go.microsoft.com/fwlink/?LinkId=152368 --> <configuration> <connectionStrings> <add name="Default" connectionString="data source=127.0.0.1;user id=aspnet_user; password=secret_password;database=membership;" providerName="MySql.Data.MySqlClient" /> </connectionStrings> <system.web> <compilation debug="true" targetFramework="4.0"> <assemblies> <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> <add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> </assemblies> </compilation> <authentication mode="Forms"> <forms loginUrl="~/Account/LogOn" path="/" timeout="2880" /> </authentication> <!--NOTE that "hashed" isn't supported with the public release of MySql.Web 6.3.5 under Mono runtime. But I can't bring myself to share sample code that doesn't hash the passwords by default.The version included with this sample project is slightly modified to allow hashed passwords in Mono. I highly recommend checking out the latest version of MySql .NET Connector. http://dev.mysql.com Also, I found that you have to rebuild MySql.Data and MySql.Web using .NET 4.0 profile if you want it to work with Asp.Net 4.0 under Mono. This is a known bug and should be published in upcoming versions of the connector. --> <membership defaultProvider="MySqlMembershipProvider"> <providers> <clear/> <add name="MySqlMembershipProvider" type="MySql.Web.Security.MySQLMembershipProvider, mysql.web" connectionStringName="Default" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="true" passwordFormat="hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" autogenerateschema="true"/> </providers> </membership> <roleManager enabled="true" defaultProvider="MySqlRoleProvider"> <providers> <clear/> <add connectionStringName="Default" applicationName="/" name="MySqlRoleProvider" type="MySql.Web.Security.MySQLRoleProvider, mysql.web" autogenerateschema="true"/> </providers> </roleManager> <profile> <providers> <clear/> <add type="MySql.Web.Security.MySqlProfileProvider, mysql.web" name="MySqlProfileProvider" applicationName="/" connectionStringName="Default" autogenerateschema="true"/> </providers> </profile> <pages> <namespaces> <add namespace="System.Web.Mvc" /> <add namespace="System.Web.Mvc.Ajax" /> <add namespace="System.Web.Mvc.Html" /> <add namespace="System.Web.Routing" /> </namespaces> </pages> <!--Don't forget to update this... I left it open to make it easier to debug.--> <customErrors mode="Off"/> </system.web> <system.data> <DbProviderFactories> <clear/> <add name="MySQL Data Provider" description="ADO.Net driver for MySQL" invariant="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data"/> </DbProviderFactories> </system.data> <system.webServer> <validation validateIntegratedModeConfiguration="false"/> <modules runAllManagedModulesForAllRequests="true"/> </system.webServer> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
Posted by scooter998 



