Solved

Custom routes in MVC

Posted on 2014-12-30
3
254 Views
Last Modified: 2015-01-13
Hi,

I am building my first MVC application and I need some advice on the routing. Right now my route looks like this:
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );

Open in new window

If I have an url that looks like this: www.site.com/Home/About it will go to the apropriate controller and run the Actionresult About().

Now, if I have an url that looks like this: www.site.com/Home/Something a resource not found message will be shown. I suppose this is standard behaviour - right?

I want to accomplish this: When the url contains an unknown part (Something in this case) I would like to run a specific ActionResult in the appropriate controller passing the unknown parameter so I can serve a view with data collected from my database - or serve my own view informing the user that the resorce doesn't exist. How do I set up this route?

Best regards
RTSol
0
Comment
Question by:RTSol
  • 2
3 Comments
 
LVL 78

Expert Comment

by:David Johnson, CD, MVP
ID: 40523590
add a default route to the bottom of your routes. Routes should be ordered from most specific to least specific..Another way is to create a custom 404 error page

Here is a link to a mvc route debugger
0
 

Author Comment

by:RTSol
ID: 40523594
Hi,

My main problem is that I don't know how to make a route that allways hits the same ActionResult for all urls - see the last part of my question. Can you help with this?

-RTSol
0
 
LVL 78

Accepted Solution

by:
David Johnson, CD, MVP earned 500 total points
ID: 40523965
For the lazy people out there:

Install-Package MagicalUnicornMvcErrorToolkit -Version 1.0
Then remove this line from global.asax
GlobalFilters.Filters.Add(new HandleErrorAttribute());

And this is only for IIS7+ and IIS Express.


There is no need to do anything custom.

For ASP.NET MVC3, all the bits and pieces are there.
Step 1 -> Update your web.config in TWO spots.

<system.web>
    <customErrors mode="On" defaultRedirect="/ServerError">
      <error statusCode="404" redirect="/NotFound" />
    </customErrors>

Open in new window

and
<system.webServer>
    <httpErrors errorMode="Custom">
      <remove statusCode="404" subStatusCode="-1" />
      <error statusCode="404" path="/NotFound" responseMode="ExecuteURL" />
      <remove statusCode="500" subStatusCode="-1" />
      <error statusCode="500" path="/ServerError" responseMode="ExecuteURL" />
    </httpErrors>    

...
<system.webServer>
...
</system.web>

Open in new window

Now take careful note of the ROUTES I've decided to use. You can use anything, but my routes are

    /NotFound <- for a 404 not found, error page.
    /ServerError <- for any other error, include errors that happen in my code. this is a 500 Internal Server Error

See how the first section in <system.web> only has one custom entry? The statusCode="404" entry? I've only listed one status code because all other errors, including the 500 Server Error (ie. those pesky error that happens when your code has a bug and crashes the user's request) .. all the other errors are handled by the setting defaultRedirect="/ServerError" .. which says, if you are not a 404 page not found, then please goto the route /ServerError.

Ok. that's out of the way.. now to my routes listed in global.asax
Step 2 - Creating the routes in Global.asax

Here's my full route section..

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.IgnoreRoute("{*favicon}", new {favicon = @"(.*/)?favicon.ico(/.*)?"});

    routes.MapRoute(
        "Error - 404",
        "NotFound",
        new { controller = "Error", action = "NotFound" }
        );

    routes.MapRoute(
        "Error - 500",
        "ServerError",
        new { controller = "Error", action = "ServerError"}
        );

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new {controller = "Home", action = "Index", id = UrlParameter.Optional}
        );
}

Open in new window

That lists two ignore routes -> axd's and favicons (ooo! bonus ignore route, for you!) Then (and the order is IMPERATIVE HERE), I have my two explicit error handling routes .. followed by any other routes. In this case, the default one. Of course, I have more, but that's special to my web site. Just make sure the error routes are at the top of the list. Order is imperative.

Finally, while we are inside our global.asax file, we do NOT globally register the HandleError attribute.

Remove this line from global.asax

GlobalFilters.Filters.Add(new HandleErrorAttribute());

Open in new window


Step 3 - Create the controller with the action methods

Now .. we add a controller with two action methods ...
public class ErrorController : Controller
{
    public ActionResult NotFound()
    {
        Response.StatusCode = (int)HttpStatusCode.NotFound;
        return View();
    }

    public ActionResult ServerError()
    {
        Response.StatusCode = (int)HttpStatusCode.InternalServerError;

        // Todo: Pass the exception into the view model, which you can make.
        //       That's an exercise, dear reader, for -you-.
        //       In case u want to pass it to the view, if you're admin, etc.
        // if (User.IsAdmin) // <-- I just made that up :) U get the idea...
        // {
        //     var exception = Server.GetLastError();
        //     // etc..
        // }

        return View();
    }

Open in new window


    // Shhh .. secret test method .. ooOOooOooOOOooohhhhhhhh
    public ActionResult ThrowError()
    {
        throw new NotImplementedException("Pew ^ Pew");
    }
}

Next, I have the two action methods. Nothing tough there. If u wish to show any exception info, then u can use Server.GetLastError() to get that info.

Bonus WTF: Yes, I made a third action method, to test error handling.
Step 4 - Create the Views

And finally, create two views. Put em in the normal view spot, for this controller.
    You don't need an Application_Error(object sender, EventArgs e)
http://bit.ly/1y47Prv
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

If I have to fix slow responding website my first thoughts are server side optimizations: the database may not be optimized or caching is not enabled, or things like that. We often overlook another major part of our web application: the client. We o…
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
Use Wufoo, an online form creation tool, to make powerful forms. Learn how to choose which pages of your form are visible to your users based on their inputs. The page rules feature provides you with an opportunity to create if:then statements for y…
Learn how to set-up custom confirmation messages to users who complete your Wufoo form. Include inputs from fields in your form, webpage redirects, and more with Wufoo’s confirmation options.

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now