Solved

Custom routes in MVC

Posted on 2014-12-30
3
298 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
3 Comments
 
LVL 81

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 81

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

The Orion Papers

Are you interested in becoming an AWS Certified Solutions Architect?

Discover a new interactive way of training for the exam.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

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…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
This video teaches users how to migrate an existing Wordpress website to a new domain.
Use Wufoo, an online form creation tool, to make powerful forms. Learn how to selectively show certain fields based on user input using rules to gather relevant information and data from your forms. The rules feature provides you with an opportunity…

726 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