Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

stackoverflow URL rewrite

How does SO perform the URL rewrite if we only put in the question ID?

questions/{id}/{whatever}

to

questions/{id}/{question-slug}

I've been working for some time with MVC and I have it working (routes, action, everything) so that it picks up the right content based on the provided ID.

However, the part after the {id} (the slug part) stays the same as typed in. So if someone typed in content/5/foobar it will display the right content but will leave the foobar in there.

In the controller (or somewhere else, please suggest where) I would need to go into the DB and pull out the right slug, put it in the route data and then perform a redirect to the same action with this correct data, I guess?

This is a try with Execute Result override. It works but does not redirect or replace/display the correct URL in browser:

    protected override void Execute(System.Web.Routing.RequestContext requestContext) {

        if (requestContext.RouteData.Values["id"] != null) {
            string currentSlug = _repository.Find(int.Parse(requestContext.RouteData.Values["id"].ToString())).Slug;
            if (requestContext.RouteData.Values["slug"] != null) {
                requestContext.RouteData.Values.Remove("slug");
            }
            requestContext.RouteData.Values.Add("slug", currentSlug);
        }

        base.Execute(requestContext);
    }

This is another, nicely working, version of a Display action, so you can see what it does and get an idea what I want:

    //
    // GET: {culture}/directory/5/{slug}
    public virtual ActionResult Display(int id, string slug)
    {
        var model = _repository.Find(id);
        if (model != null) {
            if (!model.Slug.Equals(slug, System.StringComparison.OrdinalIgnoreCase)) {
                return RedirectToActionPermanent(pndng.DirectoryEntry.ActionNames.Display, pndng.DirectoryEntry.Name, new { id = model.Id, slug = model.Slug });
            }
            return View(model);
        }
        // no model found
        return InvokeHttp404(HttpContext);
    }

This one performs permanent redirect (it does what I want) but is it right? I guess I need a redirect to refresh the browser URL, don't I?

like image 457
mare Avatar asked Nov 20 '25 10:11

mare


1 Answers

  public ActionResult Details(int id, string slug)
        {
            var session = MvcApplication.CurrentRavenSession;

            var blogPostRelations = session
                .Query<BlogPost, BlogPosts_WithRelatedData>()
                .Where(x => x.IntId == id)
                .As<BlogPostRelations>()
                .FirstOrDefault()
                ;


            if (blogPostRelations == null)
                return HttpNotFound();

            if (blogPostRelations.BlogPost.DisplayData.Slug.Value != slug)
                return RedirectToActionPermanent("Details", new { id = id, slug = blogPostRelations.BlogPost.DisplayData.Slug.Value });

            return View(blogPostRelations);
        }

Notice the:

if (blogPostRelations.BlogPost.DisplayData.Slug.Value != slug)
                    return RedirectToActionPermanent("Details", new { id = id, slug = blogPostRelations.BlogPost.DisplayData.Slug.Value });

So your #2 approach is the right one.

like image 56
Zelid Avatar answered Nov 22 '25 00:11

Zelid



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!