Reputation: 6080
I have a blogging application and users are able to create posts, I used Entity framework to create the model from the database. In Posts I have an entry for UrlSlug
.
However when I check the details of a post:
Controller:
public ActionResult Details(int id = 0)
{
Post post = db.Posts.Find(id);
if (post == null)
{
return HttpNotFound();
}
return View(post);
}
It returns a url with id
at the end: http://localhost:52202/Post/Details/1
I have tried returning post.UrlSlug (throws an error) aswell as changing my RouteConfig.cs file to use urlslug
instead of id
(which does display the urlslug, but it cant find the page because of the controller). How can I change this so urlslug is displayed instead of the Post Table Id
?
RouteConfig.cs
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
View:
@for (int i = 0; i < Model.Count(); i += 3)
{
<div class="row">
@foreach (var item in Model.Skip(i).Take(3))
{
<div class="col-md-4 portfolio-item">
<a href="@Url.Action("Details", "Post", new { id = item.Id })">
<img class="img-responsive" src="http://placehold.it/700x400" alt="">
</a>
<h3>
<a href="@Url.Action("Details", "Post", new { id = item.Id })">@Html.DisplayFor(modelItem => item.Title)</a>
</h3>
<p>@Html.DisplayFor(modelItem => item.ShortDescription)</p>
</div>
}
</div>
}
@Html.PagedListPager(Model, page => Url.Action("Index", new { page, pageSize = Model.PageSize }))
Edit
An issue I noticed is on this line:
public ActionResult Details(string urlslug)
{
Post post = db.Posts.Find(urlslug); //find only finds an eitity with a given primary key, how can I change this to find the string urlslug
Upvotes: 3
Views: 3817
Reputation: 3
An issue I noticed on the below line:
public ActionResult Details(string urlslug)
{
Post post = db.Posts.Find(urlslug); //find only finds an eitity with a given primary key, how can I change this to find the string urlslug
You can select data with the help of urlslug by using Where instead of Find
i.e. Post post = db.Posts.Where(x=> x.urlslug == urlslug).FirstOrDefault();
Upvotes: 0
Reputation: 151594
An action method does not dictate the URL, it only matches a request. You need to print the slug:
@Url.Action("Details", "Post", new { slug = item.Slug })
Then add to the routing to support the URL structure you want:
routes.MapRoute(
name: "PostWithSlug",
url: "Post/Details/{slug}",
defaults: new { }
And alter the action method:
public ActionResult Details(string slug)
{
}
But besides that, you do want an ID in the URL. Otherwise you can't use the same post title twice.
Upvotes: 5
Reputation: 1815
You can either rename your argument in your controller to match the 'slug' name. So instead of
public ActionResult Details(int id = 0)
Use
public ActionResult Details(int urlslug = 0)
Alternative is to remove id from your route config like
routes.MapRoute(
name: "Default",
url: "{controller}/{action}",
defaults: new { controller = "Home", action = "Index" }
);
Keep in mind, what ever you argument name is in your Action, that name is used as the GET variable in your url. So if the argument is int id, then your url must be like ?id=1.
Upvotes: 0