Scott Hanselman

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

September 9, '12 Comments [91] Posted in ASP.NET | Javascript | Mobile | Open Source | VS2012
Sponsored By

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 Levi Broderick along with QA by  Pranav and Anton 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()) { %>
<li><%: segment %></li>
<% } %>

UPDATE: One thing I forgot to mention was how to get the values out of the FriendlyURL. You can use things like [Form] and [QueryString] to model bind in WebForms. Now you can add [FriendlyUrlSegments] to get data out, like the ID in this example:

public SomeItem SomeItem_GetItem([FriendlyUrlSegments]int? id)
{
SomeItem item = db.SomeItem.Find(id);
return item;
}

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!

<a href="<%: FriendlyUrl.Href("~/Foo", "bar", 34) %>">Click me</a>

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.

<friendlyUrls:ViewSwitcher runat="server" />

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 derived URL resolver does just that, it resolves URLs to physical Web Forms pages. You'd then pass it into the overload of EnableFriendlyUrls(...);

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<string, string> _deviceUserAgentMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "Opera Mobi", "OperaMobile" },
{ "iPhone", "iPhone" },
{ "iPad", "iPad" }
};

protected override IList<string> 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.OperaMobile.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 friends 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.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. I am a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Sunday, September 09, 2012 6:41:26 AM UTC
Wow thats super cool :) Much awaited feature :) Thanks a lot for keeping a compatibility with 4.0. It will be really helpful for us. Thanks to Damian and Pranav! Definitely needed the feature in ASP.NET Webforms. Guys, you seriously rock \m/
Sunday, September 09, 2012 7:28:51 AM UTC
Much relief and highly awaited. Had to do so much till now to acheive url rewriting HTTPmodule, web.config, urlrewrite.xml, .......

Looking forward to it. Thank you
Sunday, September 09, 2012 7:52:24 AM UTC
Great addition to the ASP.NET WebForms Stack.

Can the QueryString Value provider still be used herewith or must one make use of the Request object as indicated in the sample?
Jacques Coertze
Sunday, September 09, 2012 7:52:59 AM UTC
Jacques - You can still have things in the QueryString like /foo?something=somevalue
Sunday, September 09, 2012 10:37:48 AM UTC
This is all great,awesome really.
It may be helpful to see (or try) the implications of the magic behind physical files vs parameters, but I bet most applications have these sorts of magic hanging non-measured (and not having notable performance cost) anyway.

However, this was generally fine with the routes support that already exists now. sure it's easier and it's hence welcome and everything, but the one really wanted feature in ASP.NET web forms I'd guess is: Multiple forms! I know it's probably very difficult to implement with the current webforms architecture though, and wouldn't be as helpful for existing projects, but for new projects, that would be the only reason I'd "happily" create a new webforms project.
Sunday, September 09, 2012 11:55:45 AM UTC
great stuff Scott, is it possible to switched off view state etc from aspx pages using new mvc like model forms?, so that we can get clean html page :).
Sunday, September 09, 2012 3:05:36 PM UTC
Much awaited feature for Webforms. Thanks for sharing Scott. These features motivate us to learn mobile web development.
Thanks for sharing. Special thanks to Damian and Pranav :)
Sunday, September 09, 2012 4:23:44 PM UTC
Suminda you can selectively turn off viewstate for the page or for some controls if you do not need viewstate
http://msdn.microsoft.com/en-us/library/system.web.ui.control.viewstatemode.aspx
Monday, September 10, 2012 2:27:14 AM UTC
This is cool, but does the mobile view stuff have any dependencies on the stuff behind this show-stopper?

Multiple DisplayModes - Caching error, will show wrong View

That bug is killing me, because it essentially breaks the alternate views. If they have different or additional @sections, and the cache breaks, you get 500's all over the place.
Monday, September 10, 2012 5:31:58 AM UTC
Thanks Jeff for the tip... I have taken note of this to make sure (if we have the same issue in FriendlyURLs as MVC's mobile implementation) this is fixed before we release the final version
Monday, September 10, 2012 2:22:43 PM UTC
This looks great, but my biggest problem with friendly URLs and Web Forms is that the Application_Error method in your Global.asax is not hit if you drop the ".aspx" extension and throw an error on that page. Any chance this works around that issue?
Monday, September 10, 2012 2:26:40 PM UTC
Thanks for this feature but we know now we have a helper method to build segments but what about any helper method in order to build a query string like :

FriendlyUrl.HrefWithQueryString("~/Foo", "bar", 34) %>

which ends up being

http://www.something.com/foo?bar=34

Monday, September 10, 2012 3:31:18 PM UTC
Thank you!
Don
Monday, September 10, 2012 4:13:18 PM UTC
@Jeff Putz, ASP.NET Friendly URLs has no dependency on the MVC/Web Pages mobile support and thus doesn't suffer from that bug. Of course if you find any issues please let us know.
Monday, September 10, 2012 4:58:43 PM UTC
We have an application that still needs to run in IIS5.1 (Windows XP).

does this work natively in IIS5.1 or would it be like routing for MVC and we would still need to add a custom mapping to the aspnet_isapi?
Monday, September 10, 2012 5:01:38 PM UTC
Every tool/feature with 'magic' needs to have a 'show me the magic' mode built in where it will dump why it did/chose something to the debug console for troubleshooting. I don't want to have to throw in random route troubleshooting tools, they should be built in!

Nice work on the urls, keep it up - looking forward to when it will be easy to configure at runtime.
Jed
Monday, September 10, 2012 5:16:31 PM UTC
Thats pretty awesome. It solves a problem I was going to have very shortly!
Monday, September 10, 2012 8:34:48 PM UTC
Rob, I cannot repro your issue. The application_end method in global.asax is called if you throw an exception from your page and browse to the page(minus the aspx extension)
Tuesday, September 11, 2012 11:00:46 PM UTC
I believe it was you who once quoted you as saying, "The less you do, the more of it you can do." So please help us do less by posting nuget commands as text instead of images that can't be cut/pasted! :P

Anyway, it looks like FriendlyUrls may make up for the lost keystrokes - thanks!
Pastey
Tuesday, September 11, 2012 11:10:04 PM UTC
Pastey - Did you notice that the NuGet string *is* in the ALT text? ;)
Wednesday, September 12, 2012 10:12:07 AM UTC
This is great. My only question is - is there a definitive list of all Microsoft supported NuGet packages somewhere, as the list is getting quite large. And perhaps more importantly the status of those packages etc.
Wednesday, September 12, 2012 9:20:56 PM UTC
Sam - We are working on JUST this! I hope for a microsoft.nuget.org soon, myself. Like 'author.nuget.org'
Thursday, September 13, 2012 12:52:00 PM UTC
How is the performance when compared to the url rewriting using Httpmodule? Have you done any comparisons? Hope this will not have any significant impact on performance.
Thursday, September 13, 2012 7:27:46 PM UTC
This is really cool! I have other questions:

when we started use following syntax in .aspx page, what made it work?

<% foreach (var segment in Request.GetFriendlyUrlSegments()) { %> <li><%: segment %></li><% } %>

Thanks!
Xiaohong Liu
Xiaohong Liu
Thursday, September 13, 2012 7:59:09 PM UTC
Xiaohong - Which? The :? That's .NET 4 and above.
Thursday, September 13, 2012 10:20:18 PM UTC
Thanks Scott, Never realize I could use <%...%> in web form aspx pages, thought only for MVC.

Added FriendlyUrls to my .NET 4 site, it works!

Xiaohong
Friday, September 14, 2012 7:51:34 AM UTC
Scott, why dont you use it on your own blog :) ?
Abdullah
Sunday, September 16, 2012 12:39:43 PM UTC
Is there any way to run this in a low trust, shared hosting environment?

Deploying it as-is yields this error, "Request for the permission of type 'System.Security.Permissions.SecurityPermission' failed".

Changing the trust level is not allowed at the current host.


thanks,
-brit
Monday, September 17, 2012 10:47:21 AM UTC
FriendlyUrl results in a conflict when there is a folder with the same name as the aspx page without the extension. What is your plan on handling that? Right now it gives priority for the folder name on a development computer.
Wednesday, September 19, 2012 4:19:28 PM UTC
Awesome! The only issue (for me) seems that the Page.PreviousPage() is broken with the re-written urls. Is there any way to get this to work??
Sunday, September 23, 2012 6:23:12 PM UTC
I really like the idea of this, however this will break debugging on a page.

Is there any easy fix for this?
Monday, October 01, 2012 4:12:29 PM UTC
I tested this sample app one several mobile devices and it will automatically send the user to the Mobile specific version of the application by default with iPhones and Windows Mobile phones.

I try hitting the URL with several Android phone browsers and it takes me to the Desktop templates by default.

Anyone have any insite on how to fix this issue for Android phones?
Monday, October 01, 2012 7:46:32 PM UTC
Mike, I suspect you could use 51Degrees.mobi to enhance the base information provided to .NET so that Android, and all other mobile platforms are better supported. Also the IsMobileExtension override in the example code looks like it could be upgraded to check for other properties such as tablets. James
Monday, October 15, 2012 1:31:53 PM UTC
OK, this sound great, BUT.... as far I can see we have to "rewrite" our project in order to make it work.

I assumed that :

1)< a href="~/About.aspx?id1=123&id2=987" runat="server">Tester < /a> would automaticly be transformed into a friendly version

2) Request.QueryString["id1"] would automaticly work when having a friendly url like "/About/id1/123"

But now we have to rewrite all our links manually AND we have to rewrite all our "getters" with the use of "GetFriendlyUrlSegments()"

Is this true or do I miss something crucial and that it already works this way? :)
Peter van der Waal
Thursday, November 15, 2012 12:37:32 AM UTC
Amazing!

Thank you Scott. It's exactly that I need.
Thursday, November 15, 2012 5:00:47 PM UTC
man , you are amazing and helpful
salem albadawi
Wednesday, November 28, 2012 5:32:19 PM UTC
How could I redirect to a completely different site if the Display Mode is NOT a Phone or a Tablet?
Jim Langdon
Friday, December 07, 2012 3:37:45 PM UTC
To make it work you need to add:
using System.Web.Routing;
into global.asax as well not only
RouteConfig.RegisterRoutes(RouteTable.Routes);

great article!
gregorio
Tuesday, January 15, 2013 4:48:25 PM UTC
Hello,
I'd like to use this package but I get the following error:
"The name 'RouteConfig' does not exist in the current context".
I just added:
using System.Web.Routing;
...
protected void Application_Start(object sender, EventArgs e)
{
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
Could you help me please?
César
Tuesday, January 15, 2013 7:51:46 PM UTC
Same error here with an empty website...
Jeff
Thursday, January 24, 2013 3:03:54 PM UTC
Nice stuff!! Group can you help me to get it working?
I'm using VS 2012 (VB.NET). I have 2 questions:
1. When I call Routes.enablefriendlyurls as indicated in this article, I get the following error: Routes.enablefriendlyurls is not a member of System.Web.Routing.RouteCollection. Why?

2. Take the following example:
How can I rewrite the url Index.aspx?articleid=123456&languageid=EN as
"Index/123456/EN"
Does someone have a working example in VB or C#?
You can mail it to mobileboy36@gmail.com

Thank you group!

Best regards.
Mobileboy
Friday, January 25, 2013 5:11:01 PM UTC
I'm getting the same issue as reported by Cesar and Jeff.

Clean asp.net Webforms 4.5 project.
"The name 'RouteConfig' does not exist in the current context".

using System.Web.Routing;
...
protected void Application_Start(object sender, EventArgs e)
{
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
Rui
Friday, January 25, 2013 5:17:36 PM UTC
OK... Fixed above issue. You must also now install (from NUGET) this : Microsoft.AspNet.FriendlyUrls.ViewSwitcher.

It seems like the latest build split out some features and dependencies into 2 packages.....just wondering what was the reason why the first package didn't also automatically pull in the 2nd package?

Rui
Friday, January 25, 2013 8:17:26 PM UTC
Rui - This from the authors: "we messed up the packages in RC. Will be fixed in RTW."

Yes you are right, include both packages and it will work. This will be fixed when it releases.
Thursday, January 31, 2013 12:19:38 AM UTC
I have Two issues!


1# If i call my URL passing parameters, like:

www.mywebsite.com/page/parameter

The "page.aspx" is called two times... (not post back) it´s two different requests by differents threads.


2# if my page have images with status 404 (not found images) and if i´m calling this page with parameters, i have N different requests o my page, where N = Number of images with 404 status.


could someone help-me?






Rafael
Wednesday, February 06, 2013 3:49:23 AM UTC
The ViewSwitcher is in C# and my project is VB, it seems like the C# code is not compiling.
Microsoft.Web.Infrastructure seems to be required but is not loaded as a dependency.

Is there a more complete example for using the ViewSwitcher, I am using the standard Site.Master from Visual Studio 2012 and the Site.Mobile.Master does not look anything like it, it looks like something from Visual Studio 2008 or 2010.
Wednesday, February 20, 2013 12:16:34 PM UTC
Hi Scott,

I am having problems trying to perform an .ajax() call with friendly URLs enabled

when
: the url = 'MyPage.aspx/MyMethod', i received a 401 Authentication failed error.

: the url = 'MyPage/MyMethod', i received the entire page page in the response

after I've commented out the "routes.EnableFriendlyUrls();"

the call is successful with the expected Response.

Is there any workaround for this?


$.ajax({
type: "POST",
url: 'MyPage.aspx/MyMethod',
data: {},
contentType: "application/json; charset=utf-8",
dataType: "text",
async: true,
cache: false,
success: function (result) {
alert('success');
},
error: function (x, e) {
alert(x.responseText);
}


Thanks
Adlie
Adlie Hendricks
Wednesday, February 20, 2013 4:47:09 PM UTC
Hey,

I'm trying this new FriendlyUrls feature but for some reason I don't get that 301 redirect when I access the page with the ".aspx" extension. If I remove it manually everything works as expected.

Any idea why?
Paulo
Wednesday, February 20, 2013 7:21:56 PM UTC
Question: Can we remove the site.mobile.master with no adverse effects? Or is there a way to programatically not call this masterpage when a user hits the site on a mobile device?
I really only want the simplified way of having friendly urls.
We're designing a website using media quieries so the mobile view will be delivered based on that.
Yes, we can split the responsive media queries into seperate css files to work with the mobile master...but it's not exactly clean since we'll now have 2 master pages to update (ie if menu needs updating)
Rui
Thursday, February 21, 2013 7:02:23 PM UTC
@Rui - Yes, it's safe to delete. If it's not there, we won't use it :)
Damian Edwards
Thursday, February 21, 2013 7:03:46 PM UTC
@Paulo - The auto-redirect was turned off for RTW as it can cause issues with some 3rd party handlers. You can turn it on again by passing a FriendlyUrlSettings object to the EnableFriendlyUrls method with the RedirectMode property set to an appropriate value.
Damian Edwards
Saturday, February 23, 2013 3:54:45 AM UTC
Really great! Thank you so much for share it.
Joel
Tuesday, February 26, 2013 4:25:58 PM UTC
Damian, thanks! :)
Paulo
Tuesday, February 26, 2013 9:20:27 PM UTC
I am lost, please help. I installed FriendlyURL from NuGet, ported the .cs code to .vb, added the DeviceSpecificWebFormsFriendlyUrlResolver class, added routes.EnableFriendlyUrls() to global.aspx.
Nothing in the resolver class is called and nothing .mobile ever gets called. I am using Visual Studio 2012 and VB. I did not notice any changes in web.config, yet the file get refreshed in the IDE, could that be the issue?
Tuesday, February 26, 2013 9:31:01 PM UTC
UPDATE:
I have added the two lines below and they have had no effect.
Dim settings As New FriendlyUrlSettings
settings.AutoRedirectMode = RedirectMode.Permanent
routes.EnableFriendlyUrls(settings)
Friday, March 01, 2013 8:29:18 PM UTC
RouteConfig.RegisterRoutes(RouteTable.Routes)

The class RouteConfig is not found.

VS 2010 VB.net Project?
Mike
Friday, March 01, 2013 9:12:57 PM UTC
To get Friendly Urls to work do the following:

1. Install the 2 following NuGet Packages
- Install Microsoft ASP.NET Friendly URLs - Core
- Install Microsoft ASP.NET Friendly URLs.

2. Read the "readme.txt" that gives you the next instructions.

3. Update your Global.asax.
<%@ import Namespace="System.Web.Routing" %>

4. Add the following call in your Application Start of Global.asax:
RouteConfig.RegisterRoutes(RouteTable.Routes)

Note: If your getting the error "RouteConfig" is not found you didn't install both friendly url packages above.

Tech Note: The Friendly Url Core Package will install a New Start Folder that contains classes and methods to support friendly urls. In VS 2010 look for the App_Start folder under the App_Core folder.
That's it, I hope this helps.
These instructions are for the ASP.NET Friendly URLs v1.0.0. Not the Pre-Release.

Mike - Giving Back after taking so much. :)
Mike
Saturday, March 09, 2013 5:24:33 AM UTC
Hi

Does anyone know how to use PageMethods with this AspNetFriendlyUrl's enabled?


Thanks
Adlie
Adlie
Sunday, March 17, 2013 3:17:46 PM UTC
Does the FriendlyURL package work with web site projects?
Or any web application projects?
Sunday, March 17, 2013 3:18:20 PM UTC
Does the FriendlyURL package work with web site projects?
Or only web application projects?
Friday, March 29, 2013 7:09:28 AM UTC
I've added both package and routing is not working, i'm using vs 2012 and my project type is Web Application 4
peter
Friday, March 29, 2013 8:13:44 AM UTC
I have an web application project in visual studio 2012, i've added the required packages and routing is not working.I'm still getting .aspx suffix.

I started my project as Empty web application and added my webforms myself.Can these be the problem.
peter
Friday, March 29, 2013 9:26:07 AM UTC
I've solved this problem
I manually removed .aspx suffix from all refernces, as Scott explained i thought that referncing the package will automatically remove the suffix.
peter
Monday, April 01, 2013 9:21:01 PM UTC
Scott,

Does this package work in Classic mode?
Tuesday, April 09, 2013 1:39:56 AM UTC
What's the best way to test the switch to the mobile version of a page? I've been testing with my Windows Phone (Nokia Lumia 920), and I can only get the desktop version of the site.
Joel H.
Friday, May 10, 2013 2:36:43 PM UTC
For VB.Net folks, rename App_Code\App_Start\RouteConfig.cs to RouteConfig.vb, and replace the contents with:

Imports System
Imports System.Collections.Generic
Imports System.Web
Imports System.Web.Routing
Imports Microsoft.AspNet.FriendlyUrls

Namespace ASP
Public Module RouteConfig
Public Sub RegisterRoutes(routes As RouteCollection)
routes.EnableFriendlyUrls()
End Sub

End Module
End Namespace
Nathan
Monday, May 13, 2013 8:09:52 PM UTC
I've said before how surprised I am that more ASP.NET Web Forms developers don't use Routing to make their URLs prettier.

Guys, here is the big secret: the customers do not care how your site's URLs look. The only URLs a user types into the browser are filenameless home page URLs that use default pages. The rest are only used in links. Users care about as much about how URLs look as they care about the style of a web site's source code.

The big value of URL rewriting is for mobile views to more easily support mobile devices. If you are using URL rewriting just to make your URLs prettier, you are wasting your time.
Claudio
Friday, May 17, 2013 4:54:50 PM UTC
Hi Scott,
This is a nice ASP.NET UrlRouting tool I have ever tried nowadays. I devepoed a asp.net web form app using this tool. Its great working my local IIS. If I deploy to my web hosting, its giving an error about SecurityPermission.
Please help me!
Thanks a lot.

Exception: System.Security.SecurityException

Message: Request for the permission of type 'System.Security.Permissions.SecurityPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.

StackTrace: at System.Web.Hosting.HostingEnvironment.RegisterObject(IRegisteredObject obj)
at Microsoft.AspNet.FriendlyUrls.Abstractions.HostingEnvironmentWrapper.RegisterObject(IRegisteredObject obj)
at Microsoft.AspNet.FriendlyUrls.Caching.StaticFileCacheRunner.GetAllFilenamesInApplication()
at Microsoft.AspNet.FriendlyUrls.Caching.StaticFileCache.<>c__DisplayClass2.<.ctor>b__0(Object _)
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
at System.Threading.ExecutionContext.runTryCode(Object userData)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
Yalcin
Friday, May 31, 2013 2:51:13 PM UTC
Hi. Adlie did you solved the problem using ajax call or pagemethods?
Omar
Friday, May 31, 2013 8:33:57 PM UTC
Yes, I just realized today that PageMethods do not work when using friendly url's. Has anyone found a solution for this?
Monday, June 24, 2013 4:56:38 AM UTC
Yalcin,
I am having the same issue with GoDaddy. The odd thing is it was working when I had basic hosting, when I upgraded to Deluxe Hosting it stopped working. Deluxe hosting also came with ASP.NET 4.5 instead of 4.0 so that might have something to do with it. GoDaddy's solution was to disable global.asax on my account (not useful).

I know GoDaddy does not support "FullTrust" on shared accounts but that would not explain why it works on Basic Hosting.

Anyone know what is going on?
Wednesday, July 03, 2013 6:29:15 AM UTC
Firstly, I would like to congratulate and thank you for coming up with such an exciting feature with Microsoft ASP.NET. Personally, I liked the option of switching between the Mobile view and desktop view. Awesome!!
Wednesday, July 10, 2013 9:29:32 AM UTC
I have some troubles using Friendly Urls and static ressources like .js or .css files.

It is the same as described here:
http://forums.asp.net/t/873722.aspx/1?Locating+Javascript+file+using+Friendly+URLs

it happens that if you use FriendlyUrl.Href("~/Details", "param") and have the URL "/Details/param?key=value" that all the files used in script tags like src="js/details.js" the request is sent to the page with the request URL "Details/js/details.js" instead of "js/details.js"

If you don't use any parameter after the page name it works fine. Is there any solution without rewriting all references in the project?
Manfred
Thursday, July 11, 2013 11:13:20 PM UTC
Manfred: Because you're passing a parameter to the Href() API, it's adding it as an extra segment to the URL. So you end up requesting the ~/Details.aspx page as “foo.com/Details/param”

Any relative paths in that page will now be treated as relative to ~/Details, as you’d expect.

To fix it, as always, scripts and other resources should not be referenced statically, but rather resolved from app relative root, e.g. ResolveUrl("~/js/details.js")
Wednesday, July 17, 2013 11:35:12 AM UTC
Thank you for the answer. This is what I have expected.

Maybe it is better to rewrite all inline included references to ResolveUrl("~") for static ressources anyway.
Manfred
Sunday, August 04, 2013 4:46:29 PM UTC
For ASP.NET MVC please check out this package I've created: https://www.nuget.org/packages/LowercaseDashedRoute/
And read the one-line configuration here: https://github.com/AtaS/lowercase-dashed-route
Friday, August 09, 2013 11:23:39 AM UTC
The following route declaration redirects perfectly for me

routes.MapPageRoute("Search", "search-directory/{searchterm}", "~/Directory.aspx");

but Request.GetFriendlyUrlSegments() returns nothing in Directory.aspx. How can I get the parameter passed?

Vikram
Saturday, August 10, 2013 8:30:20 PM UTC
When are these guys going to release the source code?
Fallon
Monday, August 12, 2013 3:27:30 PM UTC
Hi
This is awesome plugin for URL friendly rewrite.
I Just found on Google and i was trying to on my project but it is not working for me.
it giving me errors are below :
1. "Could not load type 'ASP.Site_Mobile' "
2. "Could not load type 'ASP.ViewSwicther' "

Please help me.

Thanks
Sunday, August 25, 2013 6:23:12 AM UTC
I was getting an error when using this statement:
<% foreach (var segment in Request.GetFriendlyUrlSegments()) { %>
  • <%: segment %>

  • <% } %>

    // C#: Several methods are applicable to: ... same methods though.


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

  • <% } %>
    Ray
    Wednesday, August 28, 2013 12:12:00 PM UTC
    Hi Scott,

    Will this work in a situation where one uses web forms within MVC?

    I'm asking this because my MVC projects have web forms that host reports using the Report Viewer Control.
    Thursday, September 19, 2013 1:56:55 PM UTC
    While this library is great, the documentation is awful, and the source code still isn't available after a year.
    Justin
    Thursday, September 26, 2013 6:24:22 PM UTC
    Did anyone solve that Ajax/ web page method problem? I have tried to few things and Bing'd but had no luck so far.
    Danny
    Friday, October 04, 2013 1:04:14 PM UTC
    Awesome article, managed to implement in relatively quick time. One thing I'm struggling with is where I can customise what is classed as a mobile device. Has anyone had any success with this?

    e.g. I want only iPhone to be classed as a mobile device and all others to be served the desktop version by default.

    Thanks again!
    darthtong
    Monday, October 07, 2013 5:48:02 PM UTC
    Danny - You could clear out the displayModes collection and insert just ONE:


    DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("iPhone") {
    ContextCondition = ctx => ctx.GetOverriddenUserAgent().Contains("iPhone")
    });
    Friday, October 11, 2013 12:26:22 PM UTC
    Great job!!!

    But there's a thing i dont know how it works.
    How can i get querystring mapped values?
    I know its possible via foreach ...segments
    But, is there any way for getting a value like in Request.QueryString["id"] ?

    Thanks in advance.
    marianux
    Monday, October 14, 2013 10:51:04 AM UTC
    I'm looking at implementing URL Routing on an ASP.NET Web Forms website. I've been looking at the best way to handle 404 errors so for example:


    routes.MapPageRoute("NewsRouteArticle", "news/article/{url}", "~/news.aspx")


    The URL is matched against a news article in the database.

    What happens if a news article no longer exists? How can a handle this and redirect the user to the Custom Error page? I'm aware of the issue that exists with ASP.NET where 404 Errors actually give a status code of 302 and want to try and avoid this issue (see http://imar.spaanjaars.com/497/proper-handling-of-404-errors-using-redirectmode).
    Sunday, October 20, 2013 9:57:29 AM UTC
    @Adlie Hendricks, @Omer
    I just saw your questions last night, I was also facing same problem with FriendlyURLs. I know its too late but I have found a solution by my self.
    Use direct call to a C# function from ajax, here is a post, it will help you how to call a C# function from ajax.

    <a href"http://encosia.com/using-jquery-to-directly-call-aspnet-ajax-page-methods/">http://encosia.com/using-jquery-to-directly-call-aspnet-ajax-page-methods/</a>
    Ali Shahbaz
    Sunday, October 20, 2013 8:23:44 PM UTC
    I wanted to loop back on the ajax thing. To ignore routes for .axd files I use - probably work for AJAX calls too.

    routes.Add(new Route("{resource}.axd/{*pathInfo}", new StopRoutingHandler()));

    Jeremy - regarding error pages... here is my routeconfig.cs entry

    routes.MapPageRoute("errors", "error/{friendlyurl}/{*pathInfo}", "~/error/default.aspx");

    and the web.config contains...
    <customErrors mode="On" defaultRedirect="/error/technical-difficulties" redirectMode="ResponseRewrite">
    .....
    <error statusCode="404" redirect="/error/file-not-found"/>
    </customErrors>

    while the <system.webServer> entry is

    <httpErrors>
    ....
    <remove statusCode="404" subStatusCode="-1"/>
    <error statusCode="404" prefixLanguageFilePath="" path="/error/file-not-found" responseMode="ExecuteURL"/>
    ....
    </httpErrors>

    Although, I would favor a message stating the news article does not exists when no records are returned from a database, on the news article page and use the 404 response for a more catch all type scenario.... It all depends on how your content is driven.

    Hope this helps.
    Danny
    Sunday, October 20, 2013 8:39:31 PM UTC
    Jeremy - your response status code can be set to 404 on page load. In fiddler for no records I see the response code as 404
    if (dT.Rows.Count == 0)
    {
    //send email to dl web development about link expiration.
    litCmsContent.Text = helpers.notFoundText();
    Response.StatusCode = 404;
    Response.Status = "404 Not Found";
    }

    Danny
    Monday, October 21, 2013 2:33:41 PM UTC
    Hello, I'm having trouble getting this to work with the selected item of the asp.net Menu control.
    My sitemap contains urls with the .aspx extension. I don't want to change this because then the option securityTrimmingEnabled="true" of my sitemap provider won't work as expected.
    Could you point me in the right direction in order to fix this?
    Willem
    Comments are closed.

    Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.