【发布时间】:2010-06-17 12:01:42
【问题描述】:
从 SEO 的角度来看,很高兴看到 url 的格式可以解释页面上的内容
让我们看看这种情况(这只是一个例子)
我们需要显示有关某些产品的页面,并决定为该页面设置这样的 url 模板:
/product/{ProductId}/{ProductCategory}/{ProductUrlName}。
并为此创建这样的模型
public class ProductUrlInfo{
public int ProductId{get;set;}
public string ProductCountry{get;set;}
public string ProductUrlName{get;set;}
}
我想创建控制器方法,我传递 ProductUrlInfo 对象但不是所有必填字段。上面显示的 url 模板的经典控制器方法如下
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")
实际上,当我们再添加一条路由并将其指向同一个控制器方法时,我会工作,因此路由将是:
/product/{productInfo}
/product/{ProductId}/{ProductCategory}/{ProductUrlName}
在这种情况下,路由引擎获取我们模型的字符串方法(需要覆盖它)并且它几乎总是工作。但有时它会失败并显示像
/page/?productInfo=/Cars/Porsche911
所以我的解决方法并不总是能正常工作。 有人知道如何以这种方式使用网址吗?
编辑也许不清楚,抱歉... 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 类)
用你实际传递的对象注册路由(在我的特殊情况下是 "/{key}" )
这里有一些魔法。在您想要的 url 格式路由(“/{id}/{Category}/{ProductUrlName}”和例如“/{id}/{ProductUrlName}”之后注册) 如果由于某种原因不知道其类别,您可能只想呈现名称
-
覆盖
ProductUrlInfo类中的ToString方法,它必须呈现您想要的url 格式。即公共覆盖字符串 ToString()
{
返回 (!String.IsNullOrEmpty(Category))
? string.Format( "{0}/{1}/{2}", Id, Category, ProductUrlName )
: string.Format("{0}/{1}", Id, ProductUrlName); }正如我所理解的那样:当路由引擎获得传递对象时,它会寻找适当的路由并找到 {key} 字符串。然后它发现传递的对象是一个复杂类型,并调用它的 ToString 方法。但它不是盲目地设置结果而不是 {key} 参数,而是将其与路由进行比较。 现在,如果您将 ProductUrlInfo 作为参数传递给 ActionLink,您将被转移到 Index(ProductUrlInfo key) 控制器方法。 当然,它把我看作是一个黑客,所以我想知道是否有人将对象传递给 GET 控制器方法,但以其他(更好)的方式?
【问题讨论】:
标签: asp.net-mvc asp.net-mvc-2 url-routing