2010-06-17 101 views
1

從搜索引擎優化的角度來看,很高興看到格式的網址解釋什麼是位於頁面上 讓我們看看這種情況(這僅僅是例子) 我們需要顯示有關某些產品的網頁,並決定有這樣的該頁面的網址模板: /product/{ProductId}/{ProductCategory}/{ProductUrlName}。 併爲此創建這樣的模型如何在asp.net MVC中正確地將模型轉換爲url?

public class ProductUrlInfo{ 
    public int ProductId{get;set;} 
    public string ProductCountry{get;set;} 
    public string ProductUrlName{get;set;} 
} 

我想創建控制器的方法,我通過ProductUrlInfo對象,但不是所有的必填字段。上面顯示的網址模板經典控制器方法如下

public ActionResult Index(int ProductId, string ProductCategory, string ProductUrlName){ 
    return View(); 
} 

,我們需要調用它像 Html.ActionLink<UserController>(x=>Index(user.ProductId, user.ProductCategory, user.ProductUrlName), "See user page")

我想創建這樣的控制方法

public ActionResult Index(ProductUrlInfo productInfo){ 
    return View(); 
} 

,並調用它像:Html.ActionLink<ProductController>(x=>Index(product), "See product page")

其實我工作的時候我們增加了一條路線並指向同一個控件ller方法,所以路由將是: /product/{productInfo} /product/{ProductId}/{ProductCategory}/{ProductUrlName} 在這種情況下,路由引擎獲取我們模型的字符串方法(需要覆蓋它),並且它始終工作。但有時它會失敗,並顯示URL像 /頁/?productInfo = /汽車/ Porsche911

所以我的解決方法並不總是正常工作。 有沒有人知道如何以這種方式與urls合作?

編輯也許它不清楚,對不起... ProductUrlInfo是不是查看模型。這是一個只在URL中顯示的對象。所有對象這樣的產品

public class ProductList: List<Product>{} 

public class Product{ 
    public int ProductId{get;set;} 
    public string ProductCountry{get;set;} 
    public string ProductName{get;set;} 
    public string Height{get;set;} 
    public float Price{get;set;} 

    //data which must be rendered in the url string 
    public ProductUrlInfo Key(){ 
     return new ProductUrlInfo(){ 
     ProductId = this.ProductId 
     ,ProductCountry = MyConverter.EncodeForUrl(this.ProductCountry) 
     ,ProductUrlName= MyConverter.EncodeForUrl(this.ProductName) 
     } 
    } 

} 

某處視圖控制的實例:

foreach(var pr in Model) 
    Html.RenderActionLink<ProductController>(x=>Index(pr.Key), "See product page") 

控制方法應該是這樣的:

//accept our complex object as a key 
public ActionResult Index(ProductUrlInfo key){ 
    //retrive data from database or any other stuff 
    Product pr = Repository.GetProductByKey(key); 
    return View(pr); 
} 

//accept our complex object as a key 
public ActionResult Edit(ProductUrlInfo key){ 
    //retrive data from database or any other stuff 
    Product pr = Repository.GetProductByKey(key); 
    return View(pr); 
} 

[HttpPost] 
public ActionResult Edit(Product product){ 
    //do update here 
} 

讓我來解釋它是如何傳遞給Index(ProductUrlInfo key)控制器方法。 我認爲我正在使用一些副作用。但起初如果你有幾個項目要傳遞給控制器​​,而實​​際上只有單個項目是對象主鍵(即對象ID)和其他元素,只是解釋用戶打開了哪個頁面(一些附加信息)(即對象類別和名稱)。因此,將來您可能需要更改此信息(添加新字段/刪除舊信息等)。但是,如果您在整個項目中都有該頁面的鏈接,那麼將鏈接完全替換爲新格式可能會非常痛苦。那麼爲什麼不傳遞給控制器​​一些模型,然後渲染成url? 我調查瞭如果您可以執行以下步驟將自定義對象傳遞給控制器​​ 1。創建類,它包含所有必需的字段中的URL被示出(這裏ProductUrlInfo類)

  • 寄存器路線與實際傳遞的對象(在我的特定情況下,它是「/{鍵}「)

  • 這裏有些神奇。在你想要的url格式路由之後註冊(「/{id}/{Category}/{ProductUrlName}」,例如「/{id}/{ProductUrlName}」) 您可能想渲染僅名稱if它是未知其類別由於某種原因

  • 覆蓋ToString方法在ProductUrlInfo類,它必須呈現所需的url格式。即

    公共重寫字符串的ToString()
    {
    回報(!String.IsNullOrEmpty(類別))
    ? string.Format(「{0}/{1}/{2}」,Id,Category,ProductUrlName)
    :string.Format(「{0}/{1}」,Id,ProductUrlName); }

    正如我所理解的那樣:當路由引擎獲得傳遞對象時,它會查找適當的路由並找到{key}字符串。然後它發現傳遞的對象是一個複雜的類型並調用它的ToString方法。但它不是盲目設置的結果,而不是{key}參數,但也將其與路線進行比較。 現在,如果您將ProductUrlInfo傳遞到ActionLink作爲參數,那麼您將轉入Index(ProductUrlInfo key)控制器方法。 當然,它看起來像一個黑客,所以我想知道有沒有人將對象傳遞到GET控制器方法,但以某種其他(更好)的方式?

  • 回答

    0

    只是一個建議。

    在我看來,在URL字符串中使用userID,userCountry和userLogin是一種不好的做法。這些似乎是用戶信息,而不是應用程序信息,可能看起來沒有什麼區別,但我相信有一個區別,這很重要。

    如果我有一個經過身份驗證的用戶(與已登錄的用戶不同,經過身份驗證的用戶可以匿名提供該網站允許匿名用戶),那麼我會在會話中持有他們的ID,國家,登錄信息,因爲它會可能不安全以揭示網址中的數據,也因爲它不會與搜索引擎優化相關,除非您希望淡化網站中每個網頁的重要性。雖然該網站可能會向每個用戶展示相同的頁面,但SE會看到數百個(與您擁有用戶一樣多的)URL指向它。

    我認爲將這些信息存儲在會話狀態中會更簡單,並使您的URL更加清晰,並且純粹專注於識別用戶所需的操作。

    +0

    拉撒路,感謝您的建議,但這是一個示例模型 - 第一件事就進入我的腦海。其實我不以這種方式與用戶一起工作。在產品上查看它。是的,我會改變標題中的樣本。 – Cheburek 2010-06-17 13:16:36

    +0

    您應該通過一個密鑰識別產品,其他任何內容都是應單獨處理的過濾器。 – Lazarus 2010-06-17 15:00:53

    +0

    是的,ProductId是唯一的密鑰,所有其他字段只是用戶信息。即請參閱當前頁面的地址欄。你會看到/ questions/3061430/how-to-convert-model-into-url-properly-in-asp-net-mvc其中3061430是一個pageId和「how-to-convert-model-into-url-properly-in -asp-net-mvc「 - 用戶信息。我想要做同樣的事情,但將此信息包裝到單獨的對象中 - 以防將來我應該更改網址格式... – Cheburek 2010-06-17 17:16:00

    0

    你需要urlencode你的字符串。 嘗試將ProductUrlInfo類更改爲smth。像這樣:

    public class ProductUrlInfo{ 
    
        public int ProductId{ get; set;} 
        public string ProductCountry{ get; set; } 
    
        private string productUrlName; 
        public string ProductUrlName 
        { 
         get { return HttpUtility.UrlEncode(productUrlName); } 
         set { productUrlName = HttpUtility.UrlDecode(value); } 
        } 
    } 
    

    但是,這不被認爲是一種很好的實踐,用這種方式處理ASP.NET MVC中的對象。 相反,你可以使用表單

    <% using (Html.BeginForm("Index", "User", FormMethod.Post)) 
    { %> 
    
        <%= Html.HiddenFor(model => model.ProductId) %> 
        <%= Html.HiddenFor(model => model.ProductCategory) %> 
        <%= Html.HiddenFor(model => model.ProductUrlName) %> 
    
        <input type="submit" value="See product page" /> 
    
    <% } %> 
    

    (提交按鈕是爲了簡單起見,你可以使用一個鏈接,將通過JS提交表單代替)

    您還可以創建一個單獨的索引操作一個HttpPost屬性來區分的情況下,當一個涉及到索引頁的第一次,當一個通過鏈接/按鈕來(如有必要):

    [HttpPost] 
    public ActionResult Index(ProductUrlInfo productInfo){ 
        return View(); 
    } 
    

    和路由並不需要包括ProductUrlInfo在這個案例。

    編輯: 要說清楚,拉撒路大多是正確的,對於你的情況,你不應該做你在做什麼。一個對象必須用一個鍵來標識,否則如果有人在你的URL中亂動(手動在地址欄中),你會發現不一致。例如。將類別更改爲產品不屬於的內容。

    +0

    ProductUrlInfo創建的對象只是爲了在url中顯示它。 它不是一個視圖模型。其實頁面有另一種模式。 – Cheburek 2010-06-17 16:08:27

    +0

    很抱歉,如果不清楚。我已經更新了原創帖子,試圖澄清'模型'的東西 – Cheburek 2010-06-17 16:24:18

    相關問題