ASP.NET MVC Routing 404 error - c#

First I want to show code
routes.MapRoute(
name: "SubCategory",
url: "Category/{categoryName}/{subName}",
defaults: new { controller = "Categories", action = "SubCategory", categoryName = "", subName = "" }
);
this is my route
categoryName and subName are variables
// GET: Category/{categoryName}/{subName}
public ActionResult SubCategory(string categoryName, string subName)
{
CategoriesViewResult viewResult = new CategoriesViewResult();
viewResult.Categories = _db.Categories.ToList();
viewResult.CurrentSubCategory = _db.SubCategories.First(x => x.Category.CategoryName == categoryName && x.SubCategoryName == subName);
return View(viewResult);
}
this is my method;
but I get 404.
how should i write my routes.
UPDATE
this is above default route.

Try it like this
routes.MapRoute(
"SubCategory",
"Category/Sub/{categoryName}/{subName}",
new { controller = "Categories", action = "SubCategory", apiId = UrlParameter.Optional }
);
Also, which version of MVC are you using?

Related

C# Mvc Generic Route using Slug

I'm trying to create a generic route to work with slugs, but I always got an error
The idea is, instead of www.site.com/controller/action I get in the url a friendly www.site.com/{slug}
e.g. www.site.com/Home/Open would be instead www.site.com/open-your-company
Error
server error in '/' application The Resource cannot be found
In my Global.asax I have
public static void RegisterRoutes(RouteCollection routes)
{
//routes.Clear();
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("DefaultSlug", "{slug}", new { controller = "Home", action = "Open", slug = "" });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new
{
area = "",
controller = "Home",
action = "Index",
id = UrlParameter.Optional,
slug = ""
}
);
}
In one of my cshtml I have the following link (even when it's commented, there is still the same error).
#Html.ActionLink("Open your company", "DefaultSlug", new { controller = "Home", action = "Open", slug = "open-your-company" })
EDIT: HomeController
public ActionResult Open() {
return View(new HomeModel());
}
In Global.asax you slug can not be empty,if empty ,the url will be not go to the default route
public static void RegisterRoutes(RouteCollection routes)
{
//routes.Clear();
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "DefaultSlug",
url: "{slug}",
defaults: new { controller = "Home", action = "Open" },
constraints: new{ slug=".+"});
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new
{
area = "",
controller = "Home",
action = "Index",
id = UrlParameter.Optional
}
);
}
And update the HomeController
public ActionResult Open(string slug) {
HomeModel model = contentRepository.GetBySlug(slug);
return View(model);
}
Testing Route link...
#Html.RouteLink("Open your company", routeName: "DefaultSlug", routeValues: new { controller = "Home", action = "Open", slug = "open-your-company" })
and Action link...
#Html.ActionLink("Open your company", "Open", routeValues: new { controller = "Home", action = "Open", slug = "open-your-company" })
both produces...
http://localhost:35979/open-your-company
Here's the steps I took to accomplish a similar task. This relies on a custom Slug field on the model to match against the route.
Set up your controller e.g. Controllers\PagesController.cs:
public class PagesController : Controller
{
// Regular ID-based routing
[Route("pages/{id}")]
public ActionResult Detail(int? id)
{
if(id == null)
{
return new HttpNotFoundResult();
}
var model = myContext.Pages.Single(x => x.Id == id);
if(model == null)
{
return new HttpNotFoundResult();
}
ViewBag.Title = model.Title;
return View(model);
}
// Slug-based routing - reuse View from above controller.
public ActionResult DetailSlug (string slug)
{
var model = MyDbContext.Pages.SingleOrDefault(x => x.Slug == slug);
if(model == null)
{
return new HttpNotFoundResult();
}
ViewBag.Title = model.Title;
return View("Detail", model);
}
}
Set up routing in App_Start\RouteConfig.cs
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
// Existing route register code
// Custom route - top priority
routes.MapRoute(
name: "PageSlug",
url: "{slug}",
defaults: new { controller = "Pages", action = "DetailSlug" },
constraints: new {
slug = ".+", // Passthru for no slug (goes to home page)
slugMatch = new PageSlugMatch() // Custom constraint
}
);
}
// Default MVC route setup & other custom routes
}
}
Custom IRouteConstraint implementation e.g. Utils\RouteConstraints.cs
public class PageSlugMatch : IRouteConstraint
{
private readonly MyDbContext MyDbContext = new MyDbContext();
public bool Match(
HttpContextBase httpContext,
Route route,
string parameterName,
RouteValueDictionary values,
RouteDirection routeDirection
)
{
var routeSlug = values.ContainsKey("slug") ? (string)values["slug"] : "";
bool slugMatch = false;
if (!string.IsNullOrEmpty(routeSlug))
{
slugMatch = MyDbContext.Pages.Where(x => x.Slug == routeSlug).Any();
}
return slugMatch;
}
}

How do I configure my Route config to get a URL Pattern like localhost/Product (Controller)/List (Action)/Category (Id)?

As the title says all about what I want but to be kind of specific I would like to have a URL pattern like localhost/Product/List/Category/Page but I couldn't succeed finding a solution for it. I am sure it's belong to routing and as it is difficult topic in MVC I would need your help to find a solution for it.
My route config is:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(null, "",
new
{
controller = "Home",
action = "Shop",
});
routes.MapRoute(null, "",
new
{
controller = "Product",
action = "list",
category = (string)null,
page = 1
}
);
routes.MapRoute(null, "Page{page}",
new
{
controller = "Product",
action = "List",
category = (string)null,
subcategory = (string)null
},
new { page = #"\d+" }
);
routes.MapRoute(null,
"{category}",
new { controller = "Product", action = "List", page = 1 }
);
routes.MapRoute(null,
"{category}/Page{page}",
new { controller = "Product", action = "List" },
new { page = #"\d+" }
);
routes.MapRoute(null, "{controller}/{action}");
}
}
My Controller product is:
public class ProductController : Controller
{
EFDbContext db = new EFDbContext();
private IProductsRepository repository;
public int PageSize = 4;
public ProductController (IProductsRepository productrepository)
{
this.repository = productrepository;
}
public ViewResult List(string category, int page = 1)
{
ProductsListViewModel model = new ProductsListViewModel()
{
Products = repository.Products
.Where(p => category == null || p.ProductCategory == category || p.MenSubCategory == category)
.OrderBy(p => p.ProductID)
.Skip((page - 1) * PageSize)
.Take(PageSize),
PagingInfo = new PagingInfo
{
CurrentPage = page,
ItemsPerPage = PageSize,
TotalItems = category == null ? repository.Products.Count():repository.Products.Where(e => e.ProductCategory == category).Count()
},
CurrentCategory = category
};
return View(model);
}
public PartialViewResult Menu(string subcategory = null )
{
ViewBag.SelectedCategory = subcategory;
IEnumerable<string> categories = repository.MenSubCategories
.Select(x => x.MenSubCategory)
.Distinct()
.OrderBy(x => x);
return PartialView(categories);
}
}
I hope I get answer for this as far as I really tried but couldn't find how to do it.
To generate an URL like you want: localhost/Product/List/Cars you can create a custom route like this:
routes.MapRoute(
name: "ProductList",
url: "Product/List/{category}",
defaults: new { controller = "Product", action = "List" }
);
Remember that custom routes have to come before the most general route (the one that comes with the default template).
Regarding your page parameter, if you are comfortable with this URL: localhost:3288/Product/List/teste?page=10 the above already work. But if you want this: localhost:3288/Product/List/teste/10 10 meaning the page number, then the simplest solution would be create two different routes:
routes.MapRoute(
name: "ProductList",
url: "Product/List/{category}",
defaults: new { controller = "Product", action = "List" }
);
routes.MapRoute(
name: "ProductListPage",
url: "Product/List/{category}/{page}",
defaults: new { controller = "Product", action = "List" , page = UrlParameter.Optional}
);
Another cleaner way, is to create a custom route constraint for your optional parameter. This question has a lot of answers to that:
ASP.NET MVC: Route with optional parameter, but if supplied, must match \d+
With attribute routing, you just need to decorate your action method with your specific route pattern.
public class ProductController : Controller
{
EFDbContext db = new EFDbContext();
private IProductsRepository repository;
public int PageSize = 4;
public ProductController (IProductsRepository productrepository)
{
this.repository = productrepository;
}
[Route("Product/list/{category}/{page}")]
public ViewResult List(string category, int page = 1)
{
// to do : Return something
}
}
The above route definition will send the request like yourSite/Product/list/phones and yourSite/Product/list/phones/1 to the List action method and the url segments for category and page will be mapped to the method parameters.
To enable attribute routing, you need to call the method MapMvcAttributeRoutes
method inside the RegisterRoutes method.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

RedirectToRoute doesn't work

I'm making my first web app. until now i haven't got any problems with redirectToRoute or redirectToAction. At the end of post action I want to redirect, but it doesn't work at all here is my code:
[HttpPost]
public ActionResult Delete(int id)
{
var post = this.Data
.Posts
.All()
.Where(x => x.Id == id)
.FirstOrDefault();
if (post != null)
{
var thread = this.Data
.Threads
.All()
.Where(x => x.Id == post.ThreadId)
.FirstOrDefault();
this.Data
.Posts
.Delete(post);
this.Data.SaveChanges();
return this.RedirectToRoute(CommonConstants.RedirectToRouteShowThread, new
{
area = "",
id = thread.Id,
title = thread.SubCategory.Title,
name = thread.Title,
action = "Display"
});
//return this.RedirectToRoute(CommonConstants.RedirectToRouteShowAllThreadsInSubCategory, new { Area = "", title = thread.SubCategory.Title });
// return this.Redirect("red/red");
}
return this.View();
}
I also tried different redirects just to test, but still doesn't work. I'am calling this action from js if it matters. Also I have checked if it goes inside If conditional, everything seems fine. Where is my error?
EDIT: Here are my routes
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Show thread",
url: "SubCategory/{title}/{action}/{id}-{name}/{page}",
defaults: new { controller = "Post", action = "Display", page = UrlParameter.Optional },
namespaces: new[] { "ForumSystem.Web.Controllers" });
routes.MapRoute(
name: "Create and display threads",
url: "SubCategory/{title}/{action}/{page}",
defaults: new { controller = "SubCategory", page = UrlParameter.Optional },
namespaces: new[] { "ForumSystem.Web.Controllers" });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "ForumSystem.Web.Controllers" });
}
and this is the const
public static readonly string RedirectToRouteShowThread = "Show thread";
What I mean it doesn't work is that it doesn't redirect everything else is working as expected.

Missing something simple in getting mvc route to work

It's late, I've had a lot happen today and I must be missing something very simple.
I have a route such as this:
routes.MapRoute("RequestKey", "License/RequestKey/{apello}/{requestcipher}",
new { controller = "ProductKey", action = "RequestKey" },
new { apello = "", requestcipher = "" },
new[] { "....Controllers" }
My controller action:
[ChildActionOnly]
public string RequestKey(string apello, string requestcipher)
{
return "Yeah";
}
And the url doesn't hit the controller action....time for bed?
http://localhost:53764/License/RequestKey/qwerqewrqwr/zxcvzcvzcx
Your tags indicate that you are using ASP.NET MVC 4, then try this route mapping:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{param1}/{param2}",
defaults: new { controller = "Home", action = "Index", param1 = UrlParameter.Optional, param2 = UrlParameter.Optional }
);
If you have the possibility to upgrade to ASP.NET MVC 5 then you can use Attribute routing and you should then have the possibility to write custom routes next to your Controller Action methods like this..
[Route("License/RequestKey/{apello}/{requestcipher}")]
public string RequestKey(string apello, string requestcipher)
{
return "Yeah";
}

Resource not found error

I have a problem with accessing a method on my HomeController. I show you the code of the method :
[HttpGet]
public ActionResult DecriptIdentifiantEtRedirige(string login_crypter, string mdp_crypter)
{
string loginAcrypter = _globalManager.ProtegeMotDePasse(login_crypter);
string MdpAcrypter = _globalManager.ProtegeMotDePasse(mdp_crypter);
User UserApp = new Models.User(login_crypter, mdp_crypter);
if (UserApp.AuthentificationValidee(UserApp.UserLogin, UserApp.Password))
{
Session["Name"] = UserApp.UserLogin;
return RedirectToAction("Accueil", "Home");
}
else
{
return RedirectToAction("ValiderAuthentification", "Home");
}
}
Then in the RouteConfig.cs i wrote the route like that :
routes.MapRoute(
name: "AuthentificationApresDecryptage",
url: "{controller}/{action}/{login_crypter}/{mdp_crypter}",
defaults: new { controller = "Home", action = "DecriptIdentifiantEtRedirige", login_crypter = "", mdp_crypter = "" }
);
But the problem is that when i try to access that method in the browser with that link:
"http://mydomain.com/DecriptIdentifiantEtRedirige/12345/54321"
It shows me an error : "Resource not found".
Somebody has an idea ?
Thanks.
Try this,
routes.MapRoute(
name: "AuthentificationApresDecryptage",
url: "{controller}/{action}/{login_crypter}/{mdp_crypter}",
defaults: new { controller = "Home", action = "DecriptIdentifiantEtRedirige", login_crypter = UrlParameter.Optional, mdp_crypter = UrlParameter.Optional }
);

Categories

Resources