2012-03-21 76 views
3

如果我们只输入问题ID,SO如何执行URL重写?stackoverflow URL重写

questions/{id}/{whatever} 

questions/{id}/{question-slug} 

我已经工作了一段时间,MVC和我有工作(路线,动作,一切),因此它拿起根据提供的ID正确的内容。

但是{id}(slug部分)后面的部分保持不变,所以如果有人输入content/5/foobar,它会显示正确的内容,但会将foobar留在那里。我需要进入数据库,然后把右边的弹塞拉出来,放到路径数据中,然后用这个正确的数据执行重定向到同一个动作。 , 我猜?

这是一个使用Execute Result重写的尝试。它的工作原理,但不重定向或更换/在浏览器中显示正确的网址:

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); 
    } 

这是另一个很好的工作,一个Display动作的版本,所以你可以看到它做什么,并得到一个知道我想要什么:

// 
    // 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); 
    } 

这一个执行永久重定向(它做我想要的),但它是正确的? 我想我需要一个重定向来刷新浏览器的URL,不是吗?

+0

您需要使用['RedirectResult'](http://msdn.microsoft.com/zh-cn/library/system.web.mvc.redirectresult.aspx)。 – Oded 2012-03-21 14:07:59

回答

2
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); 
     } 

注意的:

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

所以你的#2的做法是正确的。

2

你可以写这样的定制路线:

public class QuestionsRoute : Route 
{ 
    public QuestionsRoute() 
     : base(
      "questions/{id}/{slug}", 
      new RouteValueDictionary(new 
      { 
       controller = "questions", 
       action = "index", 
       slug = UrlParameter.Optional 
      }), 
      new RouteValueDictionary(new 
      { 
       id = @"\d+" 
      }), 
      new MvcRouteHandler() 
     ) 
    { } 

    public override RouteData GetRouteData(HttpContextBase httpContext) 
    { 
     var rd = base.GetRouteData(httpContext); 
     if (rd == null) 
     { 
      return null; 
     } 

     var id = rd.GetRequiredString("id"); 
     var slug = rd.Values["slug"] as string; 
     if (string.IsNullOrEmpty(slug)) 
     { 
      slug = GoFetchSlugFromDb(id); 
      if (string.IsNullOrEmpty(slug)) 
      { 
       return null; 
      } 

      httpContext.Response.RedirectToRoutePermanent(new 
      { 
       action = "index", 
       controller = "questions", 
       id = id, 
       slug = slug 
      }); 
      return null; 
     } 
     return rd; 
    } 

    private string GoFetchSlugFromDb(string id) 
    { 
     // TODO: you know what to do here 
     throw new NotImplementedException(); 
    } 
} 

将在Application_Start注册:

public static void RegisterRoutes(RouteCollection routes) 
{ 
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 
    routes.Add("questions", new QuestionsRoute()); 
} 

现在你QuestionsController将是非常简单的:

public class QuestionsController: Controller 
{ 
    public ActionResult Index(int id, string slug) 
    { 
     ... 
    } 
} 
+0

不错的选择和有用的某些情况下,但现在我会留在更简单的解决方案 – mare 2012-03-21 21:53:51