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.
Related
I have route with connected action which retrieves blog post drom database and displays it.
routes.MapRoute(
name: "GetPostToShow",
template: "posts/{postId:int}",
defaults: new { controller = "Home", action = "GetPostToShow" },
constraints: new { httpMethod = new HttpMethodRouteConstraint(new string[] { "GET" }) });
Which results in url
https://localhost:44300/posts/2002
But I want it to look like this
https://localhost:44300/posts?postId=2002
So how I can implement it?
?postId=2002 is a GET variable and can be gotten as an argument in the controller method.
So you wouild simplify your MapRoute:
routes.MapRoute(
name: "GetPostToShow",
template: "posts",
defaults: new { controller = "Home", action = "GetPostToShow" },
constraints: new { httpMethod = new HttpMethodRouteConstraint(new string[] { "GET" }) });
And in the Controller have the Method:
public IActionResult GetPostToShow(int postId)
Of course even nicer is to use the decorator routing in my opinion. Then you would remove the MapRoute call and instead add the following decorator to the method:
[HttpGet("posts")]
public IActionResult GetPostToShow(int postId)
Your routes look like below
routes.MapRoute(
name: "GetPostToShow",
template: "posts/{postId(0)}",
defaults: new { controller = "Home", action = "GetPostToShow" },
constraints: new { httpMethod = new HttpMethodRouteConstraint(new string[] { "GET" }) });
Your GetPostToShow method in controller side look like below.
public virtual IActionResult GetPostToShow (int postId)
{
// your code and return view
}
Or into CSHTML page you want to use like below code.
#Url.RouteUrl("posts", new {postId= yourpostsIdhere})
I am trying to search a movie from a list. However, the search string always returns null.
My Controller Code
public ActionResult Index()
{
return View(db.Movies.ToList());
}
public ActionResult Search(string searchstring)
{
var movies = from m in db.Movies
where m.Title.Contains(searchstring)
select m;
return View(movies.ToList());
}
// GET: Movies/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
return View(movie);
}
Routing Configuration
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Movies", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Search",
url: "{controller}/{action}/{searchstring}"
);
I am able to get the list of movies from Index action. The URL I am passing is http://localhost:52872/Movies/Search/GodFather
However if I place my Search route above the Default route, it works fine, but the edit, and details does not work.
Route conflict. First route template matches so it does not reach the second one.
Order of route definition is also important for the same reason.
Refactor to
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Search",
url: "Movies/Search/{searchstring}",
defaults: new { controller = "Movies", action = "Search"}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Movies", action = "Index", id = UrlParameter.Optional }
);
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;
}
}
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?
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 }
);