How can I create a fall-through (fallback) route for products after the default route that maps to a product controller?
Instead of example.com/product/laptop I want example.com/laptop
/product is an application that does all sorts of work. However, the product name is dynamic and new ones are added all the time.
If a route exists, then it should use the default:
example.com/about/
example.com/about/shipping
Otherwise, it is a product, and should fall through to the last route rule:
example.com/{dynamic product name fallback}
example.com/laptop
example.com/mouse
example.com/iphone
I have tried the fallback all, but it never gets to the Product controller, and it does not pass the product name which I need.
url: "{*.}"
RouteConfig:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "About", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Fall Through to Product",
url: "{productname}/",
defaults: new { controller = "Product", action = "Index" }
);
Controller
public class ProductController : Controller
{
public ActionResult Index(string productname)
{
return View();
}
}
You can't really. The default route is the default route because it catches just about everything. However, what you can do is handle the 404 by first trying to find a matching product.
In your Web.config, add the following:
<httpErrors errorMode="Custom" existingResponse="Auto">
<remove statusCode="404" />
<error statusCode="404" responseMode="ExecuteURL" path="/error/notfound" />
</httpErrors>
Then create ErrorController
:
public ActionResult NotFound()
{
// Get the requested URI
var uri = new Uri(Regex.Replace(Request.Url.OriginalString, @"^(.*?);(.*)", "$2"));
// You slug will be the `AbsolutePath`
var slug = uri.AbsolutePath.Trim('/');
// Attempt to find product
var product = db.Products.SingleOrDefault(m => m.Slug == slug);
// If no product, return 404 error page
if (product == null)
{
return View("~/Views/404.cshtml");
}
// Otherwise, return product view
Response.StatusCode = 200;
return View("~/Views/Product/Product.cshtml", product);
}