2012-03-21 41 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