In my designs, I'm avoiding any direct use of model fields as part of the URL. It's not only the question of URL-encoding them - which you can always do - but also the question of readability.
What I do instead is to add another field to the model, which is the URL-ready representation of an attribute. That field can be calculated from the original field by only accepting letters and numbers and replacing spaces or any other character with a dash.
For example, if you had the attribute set to someone's pencil + one
, the auto-created URL version of this attribute would be someone-s-pencil-one
.
You can customize this process, make it recognize some domain-specific words, etc. But that is the general idea I'm always following in my designs.
As a quick solution you can use a regular expression to isolate acceptable words and then separate them with dashes for better readability:
string encoded = string.Join("-",
Regex.Matches(attributeValue, @"[a-zA-z0-9]+")
.Cast<Match>()
.Select(match => match.Value)
.ToArray());
When done this way, you must account for possible duplicates. Part of the information is lost with this encoding.
If you fear that two models could clash with the same URL, then you have to do something to break the clash. Some websites append a GUID to the generated URL to make it unique.
Another possibility is to generate a short random string, like 3-5 letters only, and store it in the database so that you can control its uniqueness. Everything in this solution is subordinated to readability, keep that in mind.