С точки зрения 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}
В этой ситуации механизм маршрутизации получает строковый метод нашей модели (необходимо переопределить его), и он работает ПОЧТИ всегда. Но иногда это терпит неудачу и показывает как URL
/ Главная /? ProductInfo = / Автомобили / Porsche 911
Так что мой обходной путь не всегда работает должным образом.
Кто-нибудь знает, как работать с URL-адресами таким образом?
Редактировать Возможно, было неясно, извините ... 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)
}
}
}
Где-то в элементе управления View:
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)
метод контроллера.
Я думаю, что я использую какой-то побочный эффект. Но сначала, если у вас есть несколько элементов, которые вы хотите передать контроллеру, и фактически единственным элементом является первичный ключ объекта (т. Е. Идентификатор объекта), а другие элементы просто объясняют пользователю, какую страницу он открыл (некоторую дополнительную информацию) (т. Е. Категорию и имя объекта). ). Поэтому в будущем вы можете захотеть изменить эту информацию (добавить новые поля / удалить старые и т. Д.). Но если у вас есть ссылки на эту страницу со всего проекта, то может быть весьма болезненно полностью заменить ссылки на новый формат. Так почему бы не передать контроллеру какую-то модель, которая затем будет отображена в URL?
Я исследовал, что если вы можете сделать следующие шаги для передачи пользовательского объекта в контроллер
1. создать класс, который содержит все обязательные поля, которые будут отображаться в URL (класс ProductUrlInfo здесь)
зарегистрировать маршрут с фактически переданным объектом (в моем конкретном случае это " / {ключ} ")
здесь немного магии. Зарегистрируйте ПОСЛЕ того, что маршруты желаемого формата URL (" / {id} / {Category} / {ProductUrlName} " и, например, " / {id} / {ProductUrlName} ")
Возможно, вы захотите отобразить только имя, если по какой-то причине неизвестно его категорию
переопределяет ToString
метод в ProductUrlInfo
классе, и он должен отображать желаемый формат URL. т.е. * +1055 *
открытая строка переопределения ToString ()
{
return (! String.IsNullOrEmpty (Category))
? string.Format ("{0} / {1} / {2}", Id, Category, ProductUrlName)
: string.Format ("{0} / {1}", Id, ProductUrlName);
}
Как я понимаю, этот эффект: когда механизм маршрутизации получает переданный объект, он ищет соответствующий маршрут и находит строку {key}. Затем он обнаружил, что переданный объект является сложным типом, и вызывает его метод ToString. Но это не слепо установленный результат вместо параметра {key}, но также сравнивает его с маршрутами.
Теперь, если вы передадите ProductUrlInfo в ActionLink в качестве параметра, вы будете переведены в метод контроллера Index (ProductUrlInfo).
Конечно, это выглядит как хак, поэтому я хотел бы знать, есть ли кто-нибудь, кто передает объекты в метод контроллера GET, но каким-то другим (лучшим) способом?