MVC3 routes - replace id with object name - asp.net

I'm looking for a fast & elegant way of converting my object IDs with descriptive names, so that my autogenerated routes look like:
/products/oak-table-25x25-3-1
instead of
/products/5bd8c59c-fc37-40c3-bf79-dd30e79b55a5
In this sample:
uid = "5bd8c59c-fc37-40c3-bf79-dd30e79b55a5"
name = "Oak table (25x25) 3/1"
I don't even know how that feature could be named, so that I might google for it.
The problem that I see so far is the uniqueness of that "url-object-name", for example if I have two oak tables 25x35 in the db, and their names differ too little to be uniquely url-named but enough to fool the unique constraint in the db.
I'm thinking of writing that function for name-transform in SQL as an UDF, then adding a calculated field that returns it, then unique-constraining that field.
Is there some more mainstream way of achieving that?

One method is that employed by stackoverflow.com which in your case would be:
/products/5bd8c59c-fc37-40c3-bf79-dd30e79b55a5/oak-table-25x25-3-1
This ensures uniqueness, however the length of the UUID may be a deterrent. You may consider adding a sequential int or bigint identity value to the products table in addition to the uniqueidentifier field. This however would require an additional index on that column for lookup, though a similar index would be required for a Url having only a descritive string. Yet another method would be to use a hash value, seeded by date for instance, which you can compose with the descriptive name. It is simpler to rely on a sequential ID value generated by a database, but if you envision use NoSQL storage mechanisms in the future you may consider using an externally generated hash value to append.

Identity should have 2 properties: it should be unique and unchangable. If you can guarantee, that /products/oak-table-25x25-3-1 will never change to /products/oak-table-25x25-3-1-1 (remember, user can have bookmarks, that shouldn't return 404 statuscode)- you can use name as url parameter and get record by this parameter.
If you can't guarantee uniqueness or want to select record more faster - use next:
/products/123/oak-table-25x25-3-1 - get record by id (123)
/products/123/blablabla - should redirect to first, because blabla no exists or have anoher id
/products/123 - should redirect to first
And try to use more short identities - remember, that at web 2.0 url is a part of UI, and UI should be friendly.

MVC routing (actions) will handle spaces and slashes in a name. It will encode them as %20, and then decode them correctly.
Thus your URL would be /products/oak%20table%2025x25-3%2F1

I have done something very similar in an eCommerce platform I am working on.
The idea is that the URL without the unique ID is better for SEO but we didn't want the unique ID to be the product name that can change often.
The solution was to implement .NET MVC "URL slug only" functionality. The product manager creates "slugs" for every product that are unique and are assigned to products. These link to the product but the product ID and name can be changed whenever.
This allows:
domain.com/oak-table-25x25-3-1
to point to:
/products/5bd8c59c-fc37-40c3-bf79-dd30e79b55a5
(The same functionality can be used on categories too so domain.com/tables can point to domain.com/category/5b38c79c-f837-42c3-bh79-dd405479b15b5)
I have documented how I did this at:
http://makit.net/post/3380143142/dotnet-slug-only-urls

Related

Complex Rule in Drupal involving multiple entities

I need to create a fairly complex rule in Drupal - I am willing to use either code or the interface to do so.
I am more familiar with the interface, however, as opposed to the Rules API.
Anyway, the rule will be as follows:
It will happen based on a form submission from entityforms (which is one entity). It will take the checkbox value of a field (not just the true or false, but rather the value submitted when a value is true or false). It will convert this number to an integer.
At this point things get interesting - I want to create a new entity of registrations (a different entity), which as far as I can tell, means I'll have to bring a registration into scope. I also need to bring node (and not just node: type and other data selectors, but specifically node) into scope, because the next step requires it.
So at this point, I should have three entities loaded into scope:
entityforms
registration
node
I believe the best way to bring registration into scope would be entity is of type? The documentation page says that content of type should be appropriate - but that seems like it might be related to the specific use case of the example - not in my more complex example where registration isn't the first entity dealt with, but rather a second.
https://drupal.org/node/1463042
So anyway, if all three of these entities is called in correctly, the ultimate result should be the following:
Value from boolean field (not the straight 1 or 0, but whatever the value to be submitted is switched to) from the entityform is converted to an integer, and inserted where entity host ID is required. In the section where host entity type is the value should be node.
I am also open to alternative suggestions if this seems overly complex or poorly architected.
The Host Entity Type cannot be of Entityform? Why be a Node since a Registration can be attached to any entity? Then you will get the id of the Entityform as also as any other fields from that entity type instead of Node. Next steps are the same.

Beginning ASP.NET. using login name as sql parameter

Does anyone have some code or a link as to how to create the user login name as a parameter during a sql query in ASP.NET?
Basically I want to use the default membership structure with a new field ClubID, then I want to add a new table called aspnet_Clubs which contains things such as Club Name, stadium name, Balance etc etc... and then use a relationship between ClubID and a field in the aspnet_Clubs table to tie things together.
Then when each user logs in they should see the clubs information specific to their loginID.
I know the syntax to use for the query, its getting the loginname parameter and being able to use/assign it as part of the search that is causing me the problem.
In general it is not recommended to break the default schema of the aspnetdb where the Membership data is stored. It can bring you to unexpected consequences in the future.
I had a similar question a couple of days ago, please check it here, may be you will be able to adopt something from the discussion to your situation.

how to generate unique id per user?

I have a webpage Default.aspx which generate the id for each new user after that the id will be subbmitted to database on button click on Default.aspx...
if onother user is also entering the same time the id will be the same ... till they press button on default.aspx
How to get rid of this issue...so that ... each user will be alloted the unique id ...
i m using the read write code to generate unique id ..
You could use a Guid as ids. And to generate an unique id:
Guid id = Guid.NewGuid();
Another possibility is to use an automatically incremented primary column in the database so that it is the database that generates the unique identifiers.
Three options
Use a GUID: Guid.NewGuid() will generate unique GUIDs. GUIDs are, of course, much longer than an integer.
Use intelocked operations to increment a shared counter. Interlocked.Increment is thread safe. This will only work if all the requests happen in the same AppDomain: either process cycling on a refresh of the code will create a new AppDomain and restart the count.
Use an IDENTITY column in the database. The database is designed to handle this, within the request that inserts the new row, use SCOPE_IDENTITY to select the value of the identity to update in memory data (ORMs should handle this for you). (This is SQL Server, other databases have equivalent functionality.)
Of there #3 is almost certainly best.
You could generate a Guid:
Guid.NewGuid()
Or you could let the database generate it for you upon insert. One way to do this is via a Sequence. See the wikipedia article for Surrogate Keys
From the article:
A surrogate key in a database is a unique identifier for either an entity in the modeled world or an object in the database. The surrogate key is not derived from application data.
The Sequence/auto-incremented column option is going to be simpler, and easier to remember when manually querying your DB (during debugging), but the DBA at my work says he's gotten 20% increases in performance by switching to Guids. He was using Oracle, and his database was huge, though :)
I use a utility static method to generate id's, basically use the full datetime(including seconds) and generate a random number of say 3 or 4 characters and return the whole thing, then you can save it to the database.

Adding an integer ID to ASP.NET Forms Authentication

In the standard forms authentication, users are identified by a Guid. I want to give my users an UserId of type int (doesn't have to be the primary key, just something to do lookup's on).
Is it safe to add an additional column to the aspnet_users table, or should I create a new table which FKs to the UserId column and has a Unique column which generates the integer ID?
The later sounds like a bad performance hit to take just for the sake of an int!
EDIT
I want to create URLs like those on stackoverflow. eg. https://stackoverflow.com/users/23590/greg-b where the User ID is an int. For that reason I don't want to use Guids.
I'd create profiles and store the associated urlID there. Web Forms don't have Profiles available out of the box, but you can see a workaround here:
http://www.codersbarn.com/post/2008/06/01/ASPNET-Web-Site-versus-Web-Application-Project.aspx
The advantage of using Profiles is that you can tap into all the existing logic and won't have to write as much custom code yourself, aside from constructing the URL.
You could combine this with Routing for friendly URLs, if you're using ASP.NET 3.5 or up.
UPDATE: kinda similar question:
Shorter GUID using CRC

How to create a new record with a particular GUID

Using the Dynamics CRM I'm trying to create an instance of an entity. I would like to manually set the GUID, but if I had the attribute that is the primary key to the DynamicEntity, I get following error.
Service could not process request
I am building a DynamicEntity, and setting the [entityname]id attribute causes the request to fail. It's moving data between two CRM instances, so if anyone knows of a better way to copy records between CRMs, that'd work too. Otherwise, I'd like the GUID to match across instances... as that's the point of a GUID.
Happily, it IS possible to do this across two CRM instances! A co-worker knew the solution, so credit really belongs to him.
My mistake was creating a Property with type UniqueIdentifierProperty. The primary key attribute on an entity needs to be filled in with a KeyProperty. These two properties are nearly identical -- the Property types are, except that one holds a Key, the other a UniqueIdentifier. The Key/UniqueIdentifier both hold GUIDs. (Another day in the mind of Microsoft!)
Precisely, what I'm doing is creating a DynamicEntity, filling in the entity name, and filling in the majority of the attributes. The PK attribute (which you can determine from the metadata) can be filled in with a KeyProperty. I was filling it in with a UniqueIdentifierProperty, which CRM rejects and responds with a nondescript and unhelpful error message.
I apologize if I am over-simplifying the solution, but why not add a custom field in both instances that would be a mirror of the other instances guid?

Resources