2012-03-21 14 views
3

質問IDのみを入れた場合、どうすればURL書き換えを実行できますか?stackoverflow URL書き換え

questions/{id}/{question-slug} 

questions/{id}/{whatever} 

私はMVCでいくつかの時間のために働いてきたし、それが提供するIDに基づいて適切なコンテンツを拾うように、私はそれは(ルート、アクション、すべてを)働いています。

しかし、{id}後の部分は、(スラグ部分)に入力したのと同じままです。誰かがcontent/5/foobarで入力したのであれば、それは適切なコンテンツが表示されますが、そこにfoobarを残すだろう。

私はDBに入り、右のスラッグを引き出し、ルートデータに入れて、この正しいデータで同じアクションにリダイレクトする必要があるでしょう。 、 私は推測する?

これは、実行結果オーバーライドによる試行です。それは動作しますが、リダイレクトまたは交換/ブラウザに正しいURLが表示されません。

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

この1つは(それは私が何をしたいん)恒久的なリダイレクトを実行しますが、それが正しいのですか? ブラウザのURLを更新するためにリダイレクトが必要なのでしょうか?

+0

あなたが必要['RedirectResult'](http://msdn.microsoft.com/en-us/library/system.web.mvc.redirectresult.aspx)を使用してください。 – Oded

答えて

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 static void RegisterRoutes(RouteCollection routes) 
{ 
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 
    routes.Add("questions", new QuestionsRoute()); 
} 

今、あなたのQuestionsControllerはかなりシンプルになります:Application_Startに登録されます

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

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

特定の場合に便利な便利な代替方法ですが、今のところ私はもっと単純な解決方法 – mare