I’m attempting to make a TinyURL clone in ASP.NET MVC as a learning project.
Right now, all I want is to be able to submit new URLs to my /Home/Create action via a form.

I have my LINQ expression all setup, I have my routing setup, and I have my view setup but something is wrong with my setup.
Routing:
routes.MapRoute( 'Default', // Route name '', // URL with parameters new { controller = 'Home', action = 'Index' } // Parameter defaults ); routes.MapRoute( 'Redirect', '{hash}', new { controller = 'Home', action = 'RequestLink', hash = '' } );
These routes allow me to be able to go to my website, http://www.tinyurlclone.com/ and if nothing is passed ti will simply go to my Home/Index() action. However, if you put anything after the slash, it will consider that a Link Hash and attempt to retrieve the hash.
My HomeController is as follows:
[HandleError] public class HomeController : Controller { TinyGetRepository repo = new TinyGetRepository(); public ActionResult Index() { return View(); } public ActionResult Create(String url) { String hash = repo.addLink(url); ViewData['LinkHash'] = hash; return View(); } public ActionResult RequestLink(String hash) { String url = repo.getLink(hash); return Redirect(url); } }
My repo class has all my LINQ expressions in it for dealing with the database and I don’t really need to include them because it isn’t relevant to this question.
Finally, my basic Home/Index() view (used for submitting urls) is as follows:
<%@ Page Language='C#' Inherits='System.Web.Mvc.ViewPage' %> <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'> <html xmlns='http://www.w3.org/1999/xhtml' > <head runat='server'> <title>Index</title> </head> <body> <div> <center> <span style='font-size: 14pt'>TinyGet <em>(beta)</em></span><br /> <span style='font-family: Tahoma'>Reduce your long links to smaller ones to keep them more memorable....<br /> </span> <% using(Html.BeginForm('Create', 'Home')) %> <% { %> <%= Html.TextBox('url') %> <input type='submit' name='submitButton' value='Shorten Link!' /> <% } %> </center> </div> </body> </html>
However, my form simply isn’t firing any methods when I click submit.
Furthermore, if I view the source of my generated HTML I can see that it didn’t make my Form’s action correctly, it reads:
<form action='' method='post'><input id='url' name='url' type='text' value='' /> <input type='submit' name='submitButton' value='Shorten Link!' /> </form>
Why is the HTML helper putting ” as the action when it ~should~ be putting /Home/Create? Why isn’t my /Home/Create action method being called? Even if I don’t use the Html helpers and specify the <form> tag manually it throws errors.
What is wrong here?
Source for project: here
The problem is that you don’t have a route that matches the route values (controller = Home, action = Create).
You have two routes, one is the empty string (no parameters), which matches Controller = ‘Home’, Action = ‘Index’. The other is your hash route, which matches Controller = ‘Home’, Action = ‘RequestLink’. So, when ASP.Net Routing goes to build a URL from the route values you’re providing, it can’t find one (since none of them have the ‘{controller}’ and ‘{action}’ parameters).
The simplest solution, in this case, is to create a direct route to the ‘Create’ action, so that you can still use your ‘hash’ route. Put this at the top of your RegisterRoutes method. NOTE: Order does matter! ASP.Net Routing checks each route, in the order added, until it finds a match.
Since you have that ‘hash’ route, you can’t really use the default ‘{controller}/{action}/{id}’ technique, since the ‘hash’ value would be consider a valid Controller name. So, if someone requested: http://www.mysite.com/fjhas82, MVC would look for a Controller called ‘fjhas82’ and complain that it couldn’t find it. Unfortunately, this means you have to manually add new routes for each new Controller Action (like I showed above), which is a pain.
The best solution (in my opinion) is to use Regex Constraints: If your hashes have a very well-defined format (say: 5 letters followed by 2 numbers, or ‘_’ followed by any alpha-numeric characters, etc.), or if you’re willing to impose such a format, you can use the Regex constraints supported by ASP.Net Routing. Then, you’d only need these two routes
Under these routes, if MVC sees a controller name like: ‘Home’, it will check the first route, find that it doesn’t match the regular expression, and move to the next one. NOTE: My Regular Expression syntax may be a bit rusty, so I’d use something like http://regexpal.com/ to test a Regex first, to make sure it works with your hashes and controller names.
Hope that helps, I know I wrote a lot, but MVC is so flexible, you can do things in so many different ways!