Quantcast
Channel: Category Name
Viewing all articles
Browse latest Browse all 10804

Introducing ASP.NET FriendlyUrls - cleaner URLs, easier Routing, and Mobile Views for ASP.NET Web Forms

$
0
0

I've said before how surprised I am that more ASP.NET Web Forms developers don't use Routing to make their URLs prettier. If you don't want "foo.aspx" in your URL, then change it with Routes.MapPageRoute(). However, managing Routing Tables is a little tedious and most WebForms folks aren't used to the concept and don't want to invest the time.

I've also heard a number of ASP.NET Web Forms Developers express a little envy at how easy it is to make a site that has both desktop and mobile views using ASP.NET MVC. They like the idea of seeing an iPhone show up and showing a different  view while reusing logic as I've shown in my mobile talks before.

Let's solve both these problems with a new ASP.NET feature just pre-released today in alpha form on NuGet. My peer Damian Edwards and developer Pranav Rastogi have come up with a pretty awesome solution based on the original "Smarty Routes" idea from Eilon Lipton and the result is FriendlyUrls.

Install-Package Microsoft.AspNet.FriendlyUrls -pre

NOTE: If you've been paying attention to ASP.NET for the last few months you'll recognize this incremental useful but appropriately sized forward motion as being all part of the One ASP.NET master plan.

It's also worth noting that this FriendlyUrls NuGet package includes BOTH an ASP.NET 4.5 and ASP.NET 4 version so .NET 4 folks get love too.

FriendlyUrls Hello World Example

First, the obvious example. Bring up Visual Studio and File | New Project | New ASP.NET Web Forms Application. Now, from the Package Manager Console or from Manage NuGet Packages, install Microsoft.AspNet.FriendlyUrls. You'll need to "Include Prerelease" packages with -pre from the command line or via the dropdown in the UI.

Microsoft.AspNet.FriendlyUrls -pre shown in the UI

Be sure to read the readme.txt that pops up as you'll need to ensure that the FriendlyUrls routing gets called on application startup! I added this one line to my Application_Start:

RouteConfig.RegisterRoutes(RouteTable.Routes);

Here's the cool part. If I hit one of my existing links, like Contact.aspx, look what happened. See how the GET request for /Contact.aspx turned into a 301 redirect to /Contact?

/Contact.aspx turned into a 301 redirect to /Contact

If you have a Web Form called /Foo.aspx, you automatically get a /Foo route and can call your page like that! Hence, Microsoft.AspNet.FriendlyUrls.

Just by adding the one package and calling

routes.EnableFriendlyUrls();

in RouteConfig (this default came down with the NuGet package) my whole WebForms app loses its .ASPX extensions and gets reasonable defaults.

FriendlyUrls Advanced Sample

Get it? Ok, let's dig into some of the obvious next questions and some more advanced scenarios. How do I get values out of the URL? I'm used to Request.QueryString and Request.Form, but how do I get ahold of these URL segments?

Here's a Foo.aspx that I've visited via /Foo.

A basic Foo WebForms page

If I click "Click Me" the URL points to /Foo/bar/34.

Visiting /Foo/bar/34

NOTE: Be aware of the magic. It makes sense. If there was a 34.aspx in a folder called Bar in a folder called Foo, we would have used that file. There wasn't. If there was a file called Bar.aspx in a folder called Foo we would have used that. There wasn't. So, we used Foo.aspx and passed in the rest of the URL.

I can get the segments out like this:

<% foreach (var segment in Request.GetFriendlyUrlSegments()) { %>
  • <%: segment %>

  • <% } %>

    They're sitting on the Request option. I did have to import the Microsoft.AspNet.FriendlyUrls namespace to have this extension appear.

    <%@ Import Namespace="Microsoft.AspNet.FriendlyUrls" %>

    Better yet, I can generate Friendly URLs without string concatenation!

    ">Click me

    Nice, eh? OK, let's make it mobile.

    Mobile Routes with ASP.NET FriendlyUrls

    When you bring down the NuGet package you'll also get a Site.Mobile.Master. If I visit them with the Electric Plum Mobile Simulator (iPhone) I see a default mobile page, automatically.

    The Default Mobile Web Forms page in an iPhone

    Ah, you see where this is going. I'll copy Foo.aspx to Foo.Mobile.aspx. I'll make a small change. I'll visit /Foo/bar/34 again except now I get the mobile master and the mobile foo, automatically.

    image

    What I want to support switching back and forth from Desktop to Mobile? Just add a ViewSwitcher control, also included.

    Now I re-render and I get a "switch to mobile" and switch to desktop.

    image

    Now I can go back and forth between views and request a desktop site even when on mobile.

    image

    So basic mobile is nice but I might want very specific mobile views for iPhone, iPad, Opera Mobile, etc.

    Super Advanced Mobile Routes for Specific Devices with ASP.NET FriendlyUrls

    By default FriendlyUrls uses a class called WebFormsFriendlyUrlResolver but you can derive from this class and change its behavior however you like. Here's an example of a "DeviceSpecificWebFormsFriendlyUrlResolver" or, better yet, Mobile Friendly Urls for WebForms.

    This URL resolvers does just that, it resolves URLs to physical Web Forms pages.

    IMPORTANT NOTE: This code is just a very early sample, there will be a more complete one released later.

    public class DeviceSpecificWebFormsFriendlyUrlResolver : WebFormsFriendlyUrlResolver
    {
    private readonly IDictionary _deviceUserAgentMap = new Dictionary(StringComparer.OrdinalIgnoreCase)
    {
    { "Opera Mobi", "OperaMobile" },
    { "iPhone", "iPhone" },
    { "iPad", "iPad" }
    };

    protected override IList GetExtensions(HttpContextBase httpContext)
    {
    var extensions = base.GetExtensions(httpContext).ToList();
    if (extensions.Contains(MobileAspxExtension, StringComparer.OrdinalIgnoreCase))
    {
    // Base has determined we should look for a mobile page, let's add device specific
    // extension to the beginning.
    var deviceSpecificSufffix = GetDeviceSpecificSuffix(httpContext);
    if (!String.IsNullOrEmpty(deviceSpecificSufffix))
    {
    extensions.Insert(0, "." + deviceSpecificSufffix + AspxExtension);
    }
    }
    return extensions;
    }

    protected override bool IsMobileExtension(HttpContextBase httpContext, string extension)
    {
    return base.IsMobileExtension(httpContext, extension) ||
    _deviceUserAgentMap.Values.Any(v => extension.Contains(v, StringComparison.OrdinalIgnoreCase));
    }

    protected override bool TrySetMobileMasterPage(HttpContextBase httpContext, Page page, string mobileSuffix)
    {
    var deviceSpecificSufffix = GetDeviceSpecificSuffix(httpContext);
    if (!String.IsNullOrEmpty(deviceSpecificSufffix) && base.TrySetMobileMasterPage(httpContext, page, deviceSpecificSufffix))
    {
    // We were able to set a device specific master page, so just return
    return true;
    }

    // Just use the base logic
    return base.TrySetMobileMasterPage(httpContext, page, mobileSuffix);
    }

    private string GetDeviceSpecificSuffix(HttpContextBase httpContext)
    {
    foreach (var item in _deviceUserAgentMap)
    {
    if (httpContext.Request.UserAgent.Contains(item.Key, StringComparison.OrdinalIgnoreCase))
    {
    return item.Value;
    }
    }

    return String.Empty;
    }
    }

    Now we've created a map of device specific suffixes, so we can have not Foo.Mobile.aspx, but rather Foo.iPhone.aspx and Foo.OperaMobi.aspx, etc.

    Here's a little demo that loads a bunch of names into a list. Here's /async, the desktop view.

    A list of names on the desktop

    Now we'll add jQuery mobile to the mobile master page, and use it on the mobile version of the same page. We're still calling the same data source and reusing all that code.

    The list of names now as a jQuery mobile page inside an iPhone

    I'm pretty jazzed about what this means for ASP.NET and Web Forms developers. We're going to continue to push forward and improve ASP.NET even now, after Visual Studio 2012 has been released. Sometimes we'll add small features via NuGet packages, sometimes editor improvements as free VSIX Extensions like the Web Essentials playground for 2012 and larger changes via released updates to all of ASP.NET.  I hope you like the direction we're heading.

    Go play with Microsoft.AspNet.FriendlyUrls now and thank Damian and Pranav on Twitter!


    This week's sponsor: Be part of GENERATION APP. Your Idea. Your App. 30 Days. Begin your 30-day journey to create a Windows Store style app and talk 1-on-1 with a Windows 8 app development pro. Get started today.



    © 2012 Scott Hanselman. All rights reserved.

    Viewing all articles
    Browse latest Browse all 10804

    Trending Articles



    <script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>