BlogBlog

Posts tagged with: C#

Moving to Azure

Sunday, December 30, 2012 8:01 PM

Windows Azure Logo

Wow. It’s hard to believe that it’s been two months since I last wrote something on here. In the interim, I’ve been some minor architecture work under the covers here at s-church.net. I moved the site to ASP.NET MVC 4 and .NET 4.5 and upgraded to Entity Framework for database access. The site is also now hosted on the new Windows Azure Web Sites with a SQL Azure database. I was very pleasantly surprised as to how easy it was to get up and running on Azure. Publishing the completed site to Azure was as simple as downloading the publish profile for my Azure site and then selecting that profile as the destination from the Publish command in the Visual Studio 2012 Web Application project menu. The publish process updates the database connection string as necessary to connect to the associated SQL Azure data store.

I’m also in the process of building a couple of new Windows Phone apps using the Azure Mobile Services backend. It’s not quite as straightforward to use Azure Mobile Services in Windows Phone 7.5 because I have to use the REST interface directly instead of the packaged clients available for Windows Store, Windows Phone 8, and iOS apps, but it’s still a big step forward from the Microsoft Sync Framework backend that I’ve used in the past. Sync Framework requires a dedicated server where I can do binary installs, which is quite a bit more expensive from a hosting perspective.

Once completed, the whole setup should be considerably cheaper than the hosting combination of Amazon Web Services and CrystalTech/The Small Business Authority that I’ve been using for over a year now and should also be more reliable since everything is co-located again.

 
By: shane
Comments

Comments

Be the first to comment on this post

Building Stirling Money

Thursday, May 24, 2012 3:38 PM

ScreenshotTransactionsBeing my first fully native Windows Phone 7 application, Stirling Money provided me lots of opportunities to learn more about the platform. I had written a check register application for Windows Mobile 6 and wanted to take the opportunity to update it to the new Windows Phone platform. Windows Phone 7 is a radical departure from Windows Mobile from both the user’s perspective and the developer’s perspective. Building applications for the older Windows Mobile platform utilized the Microsoft .NET Compact Framework, SQL Server Compact, and a more traditional, battleship gray, Windows Forms user interface (UI). In contrast, Windows Phone 7 uses Silverlight and XAML for the UI and LINQ to SQL to access a local database.

Getting Started

To get started in Windows Phone 7, the first thing I had to do is force myself to forget everything I had learned over almost 12 years of developing mobile applications for the Microsoft Pocket PC/Windows Mobile platform. Windows Phone 7 is such a radical departure that everything I had learned about building UIs and the underlying application architecture went completely out the window. Anyone who has taken the time to become an expert in a given field can tell you just how hard that can be, and it was no different for me. I found myself having to really consciously force myself out of my old Windows Mobile development patterns, but once I got to that point, I was actually very pleasantly surprised at how easy it was to build an attractive interface that performed really well and ran rings around anything I had ever done on the older Windows Mobile platform.

The first big thing that I discovered is that there three invaluable, free toolkits that really ease the development of a Windows Phone application:

The Microsoft Silverlight Toolkit provides a whole host of native Silverlight controls for Windows Phone that you can drag and drop into the designer and use the Visual Studio properties window to manipulate. The Coding4Fun Toolkit provides more controls that really should have been built into the main framework if you ask me such as AboutPrompt, ProgressOverlay, RoundButton, and many more.

Building the UI

Even with all of these controls, building a UI in XAML is a lot like learning a foreign language. It’s just enough like XML and HTML that I’m familiar with, but with its own twists to throw me off. Data binding in XAML is particularly different than in ASP.NET or the older Windows Forms, so that was probably the biggest difference to get used to. The concept of using a view model in order to make all of the properties available to the UI was familiar to me because I use it all the time in my ASP.NET MVC development, but the binding syntax in XAML and exactly which NotifyPropertyChanged event the binding ends up listening to took some figuring out. I ended up with a number of properties in my view models that looked like the code below, with multiple NotifyPropertyChanged events, in order to get all of the related properties on the page to update when I needed them to.

private ObservableCollection<AccountViewModel> _accounts;
public ObservableCollection<AccountViewModel> Accounts
{
    get { return _accounts; }
    set
    {
        if (_accounts != value)
        {
            _accounts = value;
            if (_accounts != null)
            {
                _accounts.CollectionChanged += delegate
                {
                    NotifyPropertyChanged("Accounts");
                    NotifyPropertyChanged("TotalBalance");
                    NotifyPropertyChanged("NoDataVisibility");
                };
            }
            NotifyPropertyChanged("Accounts");
            NotifyPropertyChanged("TotalBalance");
            NotifyPropertyChanged("NoDataVisibility");
        }
    }
}

The other thing that I learned in the process is that the XAML editor in Visual Studio 2010, while much improved over previous editions, has some quirks when using static resources inside the phone:PhoneApplicationPage.Resources tag. Editing data templates in that tag doesn’t give the WYSIWYG display that editing a template inside a control does, so I often found myself editing ListItem templates inline so I could see the results in the designer and then moving the template to the Resources section once I had the design solidified.  I was pretty amazed at the amount of markup required for seemingly simple tasks. For example, one single row in the list view above required the following markup:

<DataTemplate x:Key="transactionsItemTemplate">
        <StackPanel>
            <toolkit:ContextMenuService.ContextMenu>
                <toolkit:ContextMenu>
                    <toolkit:MenuItem x:Name="menuItemEdit" Header="edit" Tag="{Binding TransactionId}" Click="menuItemEdit_Click"/>
                    <toolkit:MenuItem x:Name="menuItemDelete" Header="delete" Tag="{Binding TransactionId}" Click="menuItemDelete_Click" />
                </toolkit:ContextMenu>
            </toolkit:ContextMenuService.ContextMenu>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="5"></ColumnDefinition>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                    <ColumnDefinition Width="*"></ColumnDefinition>
                    <ColumnDefinition Width="100"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <Rectangle Grid.Column="0" 
                           Grid.Row="0" 
                           Grid.RowSpan="2" 
                           Margin="0,2,0,2"
                           Fill="{Binding TransactionColor}"/>
                <CheckBox IsChecked="{Binding Posted, Mode=TwoWay}" 
                           Tag="{Binding TransactionId, Mode=TwoWay}"
                           Grid.Row="0"
                           Grid.Column="1"
                           Grid.RowSpan="2"
                           VerticalAlignment="Center"
                           HorizontalAlignment="Center"/>
                <TextBlock Text="{Binding CheckNumber}" 
                           FontSize="{StaticResource PhoneFontSizeNormal}"
                           Padding="0,0,10,0"
                           Grid.Row="1"
                           Grid.Column="2"
                           VerticalAlignment="Center"
                           HorizontalAlignment="Left"
                           Visibility="{Binding CheckNumberVisibility}"/>
                <TextBlock Text="{Binding Location}" 
                           FontSize="{StaticResource PhoneFontSizeMediumLarge}"
                           Margin="0,0,0,0"
                           Grid.Row="0"
                           Grid.Column="2"
                           Grid.ColumnSpan="2"
                           VerticalAlignment="Center"
                           HorizontalAlignment="Left"/>
                <TextBlock Text="{Binding Category}" 
                           FontSize="{StaticResource PhoneFontSizeNormal}"
                           Margin="0,0,0,0"
                           Grid.Row="1"
                           Grid.Column="3"
                           VerticalAlignment="Center"
                           HorizontalAlignment="Left"/>
                <TextBlock Text="{Binding Amount, StringFormat=\{0:C\}}"
                           FontSize="{StaticResource PhoneFontSizeMedium}"
                           Grid.Row="0"
                           Grid.Column="4"
                           Grid.RowSpan="2"
                           Margin="5,0,5,0"
                           TextAlignment="Right"
                           VerticalAlignment="Center"/>
        </Grid>
    </StackPanel>
</DataTemplate>

Building and Accessing Data

Database support on the phone is provided through LINQ to SQL on top of SQL Server Compact 3.5.  Having used the Microsoft Entity Framework extensively in some of my recent work at EffectiveUI, using LINQ to SQL was relatively easy to pick up, though it does have some differences from the Entity Framework syntax that got me a bit in the early going. After that, it was simply a matter of translating from the database model to the view models and everything else just worked, which was way easier than writing the ADO.NET code and scripting the database creation that was required in Windows Mobile.

ScreenshotBackupThe other interesting complication was that Windows Phone does not sync files directly with the desktop. The only solution to allow the user to backup and/or restore their data from the phone is to sync with a cloud service such as SkyDrive. Fortunately the Microsoft Live SDK makes this very easy.  The following markup is all of the XAML needed to add the Sign in/Sign out button to the page:

<my:SignInButton ClientId="00000000400C1EB8" 
    Scopes="wl.signin wl.basic wl.offline_access wl.skydrive_update" 
    Branding="Skydrive" 
    Name="buttonSkyDriveSignIn" 
    SessionChanged="buttonSkyDriveSignIn_SessionChanged" />

After that, the C# code to handle the SkyDrive session changes was also very simple. All I had to do is listen for the SessionChanged event and check to see if the session status that was reported was Connected as shown in the snippet below.

private void buttonSkyDriveSignIn_SessionChanged(object sender, Microsoft.Live.Controls.LiveConnectSessionChangedEventArgs e)
{
    if (e.Status == LiveConnectSessionStatus.Connected)
    {
        _session = e.Session;
        _model.IsSignedIn = true;
        _client = new LiveConnectClient(_session);
        _client.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(_client_GetCompleted);
        _client.PostCompleted += new EventHandler<LiveOperationCompletedEventArgs>(_client_PostCompleted);
        _client.UploadCompleted += new EventHandler<LiveOperationCompletedEventArgs>(_client_UploadCompleted);
        _client.DownloadCompleted += new EventHandler<LiveDownloadCompletedEventArgs>(_client_DownloadCompleted);
        _progress.Text = "Loading...";
        _progress.IsVisible = true;
        _client.GetAsync("me/skydrive/files?filter=folders", "me/skydrive/files?filter=folders");                
        _model.InfoBoxText = "Signed in.";
    }
    else
     {
         _client = null;
         _model.IsSignedIn = false;
         _model.InfoBoxText = "Not signed in.";
     }
}

Building a Trial Mode Application

Another place where the Windows Phone tools really shined is in building a trial feature into the application. Unlike in the past, where a developer had to deal with all of the registration algorithms themselves, Microsoft does a great job of providing these checks for the developer along with the hooks into the Windows Phone Marketplace to convert from trial to paid. The code to check to see if the application is running on a trial license is very simple as shown below:

private void DetermineIsTrial()
{
#if TRIAL    
    // return true if debugging with trial enabled (DebugTrial configuration is active)    
    App.IsTrial = true;
#else
    var license = new Microsoft.Phone.Marketplace.LicenseInformation();
    App.IsTrial = license.IsTrial();
#endif
}

This method is called when the application is loaded or is activated after the user switched to a different task and set in a static variable in the main app class so that I can check for trial functionality anywhere where that check is needed.

To convert the user to a paid user from the “Buy Now” button, I only have to execute the following code to launch the Marketplace app directly to my application page. If they purchase the application while there, the DetermineIsTrial method will be called when my application is reactivated and the user will automatically see the full functionality.

private void Button_Click(object sender, RoutedEventArgs e)
{
    MarketplaceDetailTask marketplaceDetailTask = new MarketplaceDetailTask();
    marketplaceDetailTask.Show();
}

Conclusion

Being my first fully native application for Windows Phone 7, I was really pleasantly surprised as to how easy it was to build an attractive, performant app that took advantage of local database storage and cloud backup. Stirling Money took approximately 16 hours of total development time for the first release into the Windows Phone Marketplace. My next project is building a side by side comparison of building a fully-native Windows Phone application and building the same application functionality with PhoneGap/Apache Cordova and doing a comparison of the two approaches in addition to the approach of building a mobile web application within a native shell that I discussed in my article, Develop Hybrid Native and Mobile Web Apps, in the March 2012 issue of MSDN Magazine.

As of this writing, Stirling Money has been certified and published to the Windows Phone Marketplace, although it is not currently searchable yet. When it becomes available, it will be at this link. Prior to that, there is more information on my Windows Phone Software page. I will be publishing an additional post when the application goes live in the Marketplace.

 
By: Shane
Comments

Comments

Be the first to comment on this post

MSDN Magazine: Develop Hybrid Native and Mobile Web Apps

Friday, March 2, 2012 10:04 AM

MSDN Magazine: Develop Hybrid Native and Mobile Web AppsMy article on building hybrid native and mobile web applications has been published in the March issue of MSDN Magazine.

Mobile applications are all the rage these days. There are currently three major mobile platforms: Apple’s iOS  (iPhone and iPad), Google’s Android , and Microsoft’s Windows Phone , and countless variations within these platforms for the developer to consider. Focusing on any one of these platforms leaves 50% or more of the market unable to use your application, but the cost of building and maintaining the same application on each of the platforms quickly becomes problematic. A web application is another option, but one that leaves the experience diluted and leaves the developer without access to many of the native hardware capabilities. 

In one of my recent projects at EffectiveUI, I spent a lot of time thinking about how to solve this conundrum in a way that provides the best possible user experience while still being cost effective and maintainable. My solution was an application that is a hybrid of a native application and a mobile web application. I had the opportunity to share this solution, and provide a tutorial for building it, in an article for MSDN Magazine , “Develop Hybrid Native and Mobile Web Apps .” I truly believe that this approach is a “best of both worlds” solution that leaves the developer and end user in a better place.

I hope that my approach to this problem helps you in building your applications and I’d love to hear any feedback that anyone might have.

The main text of this post is also cross-posted on the EffectiveUI blog.

 
By: Shane
11 Comments

Comments

  • Ruurd Eijzinga 3/15/20123:48 AM Great article, is there a version for vs2010 ?
  • Shane Church 3/15/20127:48 AM @Ruurd: All of the ASP.NET MVC and Windows Phone 7 code samples in the article are for Visual Studio 2010. The Android project requires Eclipse and the Android SDK and the iOS code requires Apple OS X and XCode.
  • Ruurd 3/15/20128:20 AM sorry, but I get these errors EffectiveUI.MSDN.Web.csproj' cannot be opened. The project type is not supported by this installation. EffectiveUI.MSDN.Phone.csproj' cannot be opened. The project type is not supported by this installation. I am running vs2010 sp1
  • Shane Church 3/15/20128:48 AM You will need the ASP.NET MVC 3 components for the Web project from http://www.asp.net/mvc. You will also need the Windows Phone 7.1 SDK for the Phone project from http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=27570.
  • Kushil Abeyguna 3/25/20123:51 PM Good article. I think many people already have been developing hybrid (HTML5/JavaScript running in a native wrapper) mobile application using open source frameworks such as PhoneGap (which supports six mobile platforms). But I never thought of developing these native shells by myself. This is a good eye opener for most people like me as they would have never thought that their favorite frameworks do a "similar" thing to the above in their native wrappers. Good work indeed. I do not have to stick to a bridging framework like PhoneGap anymore.
  • Shane Church 3/27/20129:18 AM Kushil, (cross-posted from blog.effectiveui.com) Comparing this solution to one like PhoneGap (now Apache Cordova) is a matter of degree. To me, the big difference in the solutions is that Cordova is designed to allow a HTML/JavaScript developer to build a device native application. For that to happen, some of the HTML and JavaScript have to be deployed to the device itself and there remains a dependency on the Cordova JavaScript APIs for native hardware access. On the other hand, the solution I present in the article takes a cross-platform mobile web application and provides it with access to native functionality as needed. The hybrid technique that I describe in the article provides a much finer level of control over the user experience when compared to Cordova and also has the advantage of being accessible on devices that do not have the native application installed. As I stated in the article, none of these approaches are inherently better than the others and you really need to make sure that you keep the business and end user goals in the forefront when choosing a technology stack for a mobile application.
  • ALex 3/29/20121:25 AM Hi Shane, this seems like a very useful approach! Thank you. Having to write just 1 Web Application and still have access to the ressources of the device can save a lot of time. But I am wondering if this approach could also enable the webapplication to be accessible offline? What do you think?
  • Shane Church 3/29/20123:49 PM Alex, Depending on how you architect the site, you could likely make large portions of the site available offline using the HTML5 ApplicationCache interface (http://www.html5rocks.com/en/tutorials/appcache/beginner/). It really depends on how dynamic the data in the site is as to how much you could make available offline. I think it would be extremely challenging to make the entire content of anything other than a completely static site available offline. More likely, you could use the HTML5 ApplicationCache interface to speed loading of portions of your app by caching images and CSS files on the user device. I hope this helps!
  • ALex 3/30/20125:58 AM Thank you very much. I think the approach you are using and the new things that are coming like SPA on mvc 4 (http://channel9.msdn.com/Events/TechDays/Techdays-2012-the-Netherlands/2159) will be very powerful!
  • Mark L 4/16/20129:35 PM Hi Shane, I've just downloaded the sample code from your article, but the Android code doesn't compile as it appears to be missing a referenced library. I get this error: Project 'EffectiveUI.MSDN' is missing required library: 'C:\Users\Shane.Church\Documents\Cartegraph\httpmime-4.1.2.jar' Any chance of posting an updated sample code package that includes this library? Or am I being a numb nuts and it's already there? "
  • Shane Church 4/17/20121:28 PM Mark, The httpmime-4.1.2.jar is part of the Apache HttpComponents project at http://hc.apache.org/index.html. You can download the HttpClient 4.1.3 (GA) release binaries which include httpmime-4.1.3.jar and update the reference in Eclipse.

Rebuilding s-church.net

Friday, December 16, 2011 4:00 PM

Shane.Church.Web Project StructureAlong with the posts that I’ve been getting back into making recently, I also spent quite a bit of time recently redeveloping the infrastructure of s-church.net.  I rebuilt the site from the ground up using ASP.NET MVC 3, HTML5, CSS 3, and jQuery and I’d like to take some time to describe what I did from a technical standpoint.

The first part of what I did was to create a new ASP.NET MVC 3 project in Visual Studio.  I then analyzed my existing site and and created MVC controllers for each of the main menu items that you see above.  I rebuilt the main _Layout.cshtml master page for the site using HTML5 and the ASP.NET MVC 3 Razor view engine as seen in  Master Layout code snippet below.  I take advantage of the new HTML5 semantic tags like <header>, <nav>, <section>, <article>, and <footer>.  The <header>, <nav>, and <footer> tags are relatively straightforward in their usage, but the <section> and <article> tags are less obvious.  In this site, I use <section> as a container for various pieces of the layout.  Each blog post or photo item container is an <article> in the semantic markup.

 
<div class="page">
        <header>
            <div id="title">
                <h1>@ViewBag.Header</h1>
            </div>
        </header>
        <nav>
            <ul class="ssc_nav">
                <li>@Html.ActionLink("Home", "Index", "Home")</li>
                <li><a href="@Url.Content("~/Resume.pdf")">Resume</a></li>
                <li>@Html.ActionLink("Blog", "Index", "Blog")</li>
                <li>@Html.ActionLink("Photo Album", "Index", "PhotoAlbum")</li>
                <li>
                    <a href="#">Software</a>
                    <div class="ssc_sub_nav">
                        @Html.ActionLink("Windows 7 Gadgets", "Win7Gadgets", "Software")
                        @Html.ActionLink("Windows Mobile Smartphone", "WMSmartphone", "Software")
                        @Html.ActionLink("Windows Mobile Pocket PC", "WMPocketPC", "Software")
                        @Html.ActionLink("Windows", "MSWindows", "Software")
                        @Html.ActionLink("Pocket PC", "MSPocketPC", "Software")
                        @Html.ActionLink("Palm OS", "Palm", "Software")
                    </div>
                </li>
                <li>
                    @Html.ActionLink("Reading List", "Index", "ReadingList")
                </li>
                @if (Request.IsAuthenticated && User.IsInRole("Admin"))
    {
                <li>@Html.ActionLink("Admin", "Index", "Admin")</li>
    }
            </ul>
        </nav>
        <section id="main">
            <div class="main_container">
                @RenderBody()
            </div>
            <div class="side_nav">
                <div class="container">
                    <img src="@Url.Content("~/Content/Images/side_nav_photo.jpg")" alt="Shane Church, Andrea Love, and Ethan Love-Church" class="side_photo" />
                    <h3>Contact</h3>
                    <a href="mailto:shane@s-church.net" class="logo_link">Email Me</a>
                    @RenderSection("SideNav", false)
                </div>
                @RenderSection("SideNavPostContainer", false)
            </div>
            <div class="clear">&nbsp;</div>
        </section>
        <footer>
            <div id="logindisplay">
                @Html.Partial("_LogOnPartial")
            </div>
            Copyright &copy; Shane Church 2011
        </footer>
    </div>

I built the menu hover and drop down behaviors myself using jQuery and some CSS.  The behavior is relatively straightforward and, as I’ve been learning more about HTML, CSS, and JavaScript in my role at EffectiveUI, I found it very easy to implement the menu on my own as shown in the code snippet below.

var menuTimeout = null;

$(document).ready(function () {
    $(".ssc_nav li").mouseenter(function () {
        var $this = $(this);
        $this.find(".ssc_sub_nav").slideDown(200, function () {
            menuTimeout = window.setTimeout(function () {
                $this.find(".ssc_sub_nav").slideUp(200);
            }, 500);
        });
    });

    $(".ssc_sub_nav a").mouseenter(function () {
        window.clearTimeout(menuTimeout);
        menuTimeout = null;
    });

    $(".ssc_sub_nav a").mouseleave(function () {
        window.clearTimeout(menuTimeout);
        menuTimeout = null;
        var $this = $(this);
        menuTimeout = window.setTimeout(function () {
            $this.parent().slideUp(200);
        }, 500);
    });
});

All of the styling of the new site is using CSS 3 with minimal use of images for item backgrounds.  This significantly improves the download size and speed of the individual pages by reducing the number of HTTP requests for images and allowing the browser to do the rendering work.  I’m using Eric Meyer’s Reset CSS to reset all of the CSS settings across all browsers before applying my own styling to achieve consistency between all of the different browsers.  One annoyance to me in the new CSS 3 implementations is the addition of browser specific prefixes like -moz- for Firefox and -webkit- for Chrome and Safari and -ie- for Internet Explorer.  This requires me as the developer to know a lot more about the workings of each browser to achieve consistent results and I end up having the W3Schools reference pages open constantly while developing.  For example, the gradient in the main menu is described by the CSS code below.

ul.ssc_nav {
    height: 34px;
    background: #999999; /* Old browsers */
    background: -moz-linear-gradient(top, #999999 0%, #5B5B5B 100%); /* FF3.6+ */
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#999999), color-stop(100%,#5B5B5B)); /* Chrome,Safari4+ */
    background: -webkit-linear-gradient(top, #999999 0%,#5B5B5B 100%); /* Chrome10+,Safari5.1+ */
    background: -o-linear-gradient(top, #999999 0%,#5B5B5B 100%); /* Opera11.10+ */
    background: -ms-linear-gradient(top, #999999 0%,#5B5B5B 100%); /* IE10+ */
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#999999', endColorstr='#5B5B5B',GradientType=0 ); /* IE6-9 */
    background: linear-gradient(top, #999999 0%,#5B5B5B 100%); /* W3C */
    border-top: 1px solid #000000;
    border-bottom: 1px solid #000000;
    z-index: 200;
}

I wanted to make sure that I maintained all of the existing links which were in the format of /Blog.aspx?id=<id> even though I was switching the site to use a more SEO-friendly URL routing scheme of /Blog/<id>, so I added a route in Global.asax to my LegacyController which then executes a HTTP 301 Permanent Redirect to the new URL so that search engines and people with favorites marked for the old URLs will continue to work correctly.  The routing entry is as follows:

routes.MapRoute(
        "{*allaspx}",
        @"{id}.aspx",
        new { controller = "Legacy", action = "Index" });

and the PermanentRedirectResult MVC action is highlighted below.

public class PermanentRedirectResult: ActionResult
{
    //...

    public override void ExecuteResult(ControllerContext context)
    {
        if (_action == null || _controller == null)
        {
            context.HttpContext.Response.Status = "404 Not Found";
            context.HttpContext.Response.StatusCode = 404;
        }
        else
        {
            context.HttpContext.Response.Status = "301 Moved Permanently";
            context.HttpContext.Response.StatusCode = 301;
            context.HttpContext.Response.AppendHeader("Location", ((Controller)(context.Controller)).Url.Action(_action, _controller, _routeValues));
        }
    }
}

ScreensaverDuring the transition, I also converted my photo album from local file storage to use Amazon’s S3 service.  This change required me to implement a simple controller to use Amazon’s AWS SDK and then I added an ASP.NET MVC controller method in my photo album controller to actually respond with the image from the Amazon service as shown below.  This conversion also required me to retool my custom screensaver that displays images from this site (shown to the left) and my Windows Live Photo Gallery plugin for publishing images to the site to use the Amazon S3 service as well.

 
public ActionResult Image(long id)
{
    MySQLSiteModel model = new MySQLSiteModel();
    var photo = (from p in model.photo
                 join pg in model.page on p.LINK_ID equals pg.ID
                 where p.ID == id
                 select new PhotoViewModel() { ID = p.ID, CategoryID = pg.ID, CategoryName = pg.DISPLAY_NAME, Caption = p.CAPTION, File = p.FILE, UpdatedDate = p.UPDATED_DATE }).FirstOrDefault();

    try
    {
        S3Controller amazonController = new S3Controller();

        Stream data = amazonController.ReadObject("photos", photo.CategoryID.ToLower() + "." + photo.File.Substring(photo.File.LastIndexOf('/') + 1).ToLower());

        return File(data, "image/jpeg");
    }
    catch
    {
        return new HttpStatusCodeResult(404);
    }
}

As you can see illustrated in the snippet above, I have also moved my database connection code to use the Microsoft Entity Framework using the MySQL .NET provider.  The database connections are then handled in code using LINQ-to-Entities, significantly reducing the amount of raw SQL code that I needed.  I did run into some issues with the MySQL provider not supporting some of the standard LINQ operations like .Take() consistently, though I don’t have a good code example for that since I came up with some workarounds.

I also implemented the Metaweblog API in order to facilitate using Windows Live Writer to publish to the blog.  I implemented this using the XML-RPC.Net library as a ASP.NET generic handler.  The interface is shown below.

public interface IMetaWeblog
{
    #region MetaWeblog API

    [XmlRpcMethod("metaWeblog.newPost")]
    string AddPost(string blogid, string username, string password, Post post, bool publish);

    [XmlRpcMethod("metaWeblog.editPost")]
    bool UpdatePost(string postid, string username, string password, Post post, bool publish);

    [XmlRpcMethod("metaWeblog.getPost")]
    Post GetPost(string postid, string username, string password);

    [XmlRpcMethod("metaWeblog.getCategories")]
    CategoryInfo[] GetCategories(string blogid, string username, string password);

    [XmlRpcMethod("metaWeblog.getRecentPosts")]
    Post[] GetRecentPosts(string blogid, string username, string password, int numberOfPosts);

    [XmlRpcMethod("metaWeblog.newMediaObject")]
    MediaObjectInfo NewMediaObject(string blogid, string username, string password,
        MediaObject mediaObject);

    #endregion

    #region Blogger API

    [XmlRpcMethod("blogger.deletePost")]
    [return: XmlRpcReturnValue(Description = "Returns true.")]
    bool DeletePost(string key, string postid, string username, string password, bool publish);

    [XmlRpcMethod("blogger.getUsersBlogs")]
    BlogInfo[] GetUsersBlogs(string key, string username, string password);

    [XmlRpcMethod("blogger.getUserInfo")]
    UserInfo GetUserInfo(string key, string username, string password);

    #endregion
}

One final piece to note is the use of jQuery to make the pages more interactive.  For each major section of the site, I wrote the code as a jQuery Plugin in order to encapsulate the code for each section.  This is a technique that we commonly use at EffectiveUI to make it easier for our clients to maintain the code after a project is complete.  An example from the Photo Album plugin that I wrote is shown below.

//jquery.PhotoAlbum.js
//Copyright © Shane Church 2011

(function ($) {
    var methods = {
        init: function () { },
        loadPage: function (options) {
            var defaults = {
                href: "",
                callback: function () { }
            };

            var opts = $.extend(defaults, options);

            var $this = $(this);

            $.ajax({
                url: opts.href,
                type: "GET",
                dataType: 'html',
                success: function (data) {
                    var $data = $(data);

                    $(".photos_container").empty();
                    $(".photos_container").append($data.find(".photos_container").children());

                    $(".pager").empty();
                    $(".pager").append($data.find(".pager").children());

                    opts.callback();
                },
                error: function (request, status, error) {
                }
            });
        },
        showPhoto: function (options) {
            var defaults = {
                href: "",
                title: "",
                category: "",
                file: "",
                callback: function () { }
            };

            var opts = $.extend(defaults, options);

            var $content = $("#modal-view-photo");
            $content.find(".image img").attr("src", opts.file).attr("alt", opts.category + " - " + opts.title);
            $content.find("h4").text(opts.title);
            $content.find("h5").text(opts.category);
            $content.find("a.close").unbind("click").click(function () {
                $().HideModal({ strId: "#modal-view-photo" });
                return false;
            });

            var options = {
                strId: "#modal-view-photo"
            };

            $().ShowModal(options);
        }
    };

    $.fn.PhotoAlbum = function (method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
            return methods.init.apply(this, arguments);
        } else {
            $.error('Method ' + method + ' does not exist on jQuery.PhotoAlbum');
        }
    };

})(jQuery);

As you can see, this was a pretty major rearchitecture of the entire site, but it gave me the opportunity to put a lot of the new techniques that I’ve learned over the last year into practice as well as build an updated portfolio site.  I hope this detailed tour of the site proves useful.  Feel free to comment or contact me directly with any comments or questions!

 
By: Shane
Comments

Comments

Be the first to comment on this post

MSDN Magazine

Monday, December 5, 2011 2:42 PM

MSDNMagazineSmallLogoA few weeks ago, I submitted an abstract of an article on the Cartegraph mobile prototype that I worked on for EffectiveUI to MSDN Magazine.  The concept is about addressing the costs of building a mobile application for all of the rapidly proliferating mobile platforms (iPhone, iPad, Android, Windows Phone) by building the application primarily as a web application using ASP.NET MVC 3 and jQuery Mobile while still being able to leverage native hardware features like the camera, GPS, or accelerometer.  A few minutes ago I got a phone call from Dr. James McCaffrey of Microsoft Research and author of MSDN Magazine’s monthly Test Run column.  The magazine editors liked the abstract, had asked him to review my submission from a technical perspective and he had a few clarifying questions that he wanted to ask.  He really liked the idea and is recommending to them that they move forward with the idea toward publication.  He commented that the abstract was really well written and also offered some advice about how to catch the readers with the concept in the first few sentences of the article.  Hopefully, with any luck, I’ll have a byline in MSDN Magazine here in a few months.

 
By: Shane
2 Comments

Comments

  • Ryan Comingdeer 2/29/20124:21 PM I read your article today in the March MSDN issue. I love the concept of MVC 3 powering mobile apps. Today I do most of my web apps in MVC 3 and I do a ton of Mobile apps using Phonegap and JQuery Mobile. However, one very important note that you didn't mention in your article was that if you develop the app the way you suggested, Apple will NOT approve the app to the public iTunes store. You would be fine on Windows and Android but the Apple team does not allow an app to be just a browser pointing to a website. We have had this issue a number of times with PhoneGap even if the files reside in the app. For some reason, Apple wants to make sure the app is utilizing some portion of Native code before it gets approved. Very sad, but very true. Have you been able to work around this issue?
  • Shane Church 3/2/201210:00 AM Ryan, With this proof of concept application, we didn't go as far as publishing to the app store. A modification that could be made to make it pass Apple's scrutiny would be to make the login page native on the Apple platform.