Help with MVC 3 Routes - c#

I have a simple route structure in my MVC 3 app that is breaking in an unexpected way.
My URL structure is fairly simple, but contains a handful of variables.
http://site.com/{location}/{stage}/{controller}/{action}/{id}
examples:
http://site.com/ny/prod/server/list - list all prod servers in ny
http://site.com/ny/test/server/123456 - list the details for the server in ny, in the test stage, with id 123456
http://site.com/ny/prod/server/reboot/565656 - reboot the server in ny, in the prod stage, with id 565656
I created the following route in my Global.asax file.
routes.MapRoute("Default", "{location}/{stage}/{controller}/{action}/{id}", new {controller="server", action="list", id = UrlParameter.Optional});
This works fine for displaying a list of servers and the details of a server at /server/details/id, but when I try to execute a reboot, I get an error.
URL: http://site.com/ny/prod/server/reboot/565656
The view 'ny' or its master was not found or no view engine supports
the searched locations. The following locations were searched: ...
Why would it try to look for a view name ny.cshtml?

i think your problem is that you are either not using a constraint to define what location and stage should look like and it is giving you false positives and reading things in where they are not supposed to or you have your route definitions in the wrong order
make sure you have the default mvc defined last and if you have multiple custom routes constrain the either using a regex or custom constraint class to define what locations are valid and they should look like
eg http://site.com/ny/test/server/123456
is ny a valid location - make a custom constraint that defines what a
valid location is validate it against a database or a list of valid
locations
is test a valid stage - regex could be sufficient but i always try to avoid regex whenever possible as it is evil and hard to maintain. again i would write a custom constraint to define what stages are valid likely validating against a list is sufficient is the case as you shouldnt have very many stages
also to be noted with using stages the way you are in your url you can also add authentication rules in a constraint so that for exaple only people that are ..say.. admin or stakeholder roles be mached to the route and regular or non authenticated users would simply fall through to the next route or can simply give a 404
writing routes can be tricky so it is advised to contrain your input data as much as you can especially if you are accepting string data
stephen walther has a good post on writing route constraint at his blog

Related

Does IIS Metabase return sites in Id ascending order?

I'm not sure if my question on the face of it makes full sense, so let me try and elaborate. At the moment I try and check if a website already exists in IIS by creating a new DirectoryEntry:
DirectoryEntry IISWebsites = new DirectoryEntry(MetaBasePath);
MetaBasePath is defined earlier as:
private const string MetaBasePath = "IIS://Localhost/W3SVC";
I check IISWebsites children in a foreach loop and just wondered if this will run through the children in Id order? From what I've read this is actually stored in the DirectoryEntry 'Name' property.
The reason I ask is that if the website name entered by the user in my web setup project isn't found then I want to return the highest id so I can add 1 to it and create a new website with the name supplied by the user.
Having tested this with my IIS it does seem to return it in this order but I need to be sure.
EDIT
I've found the following on Microsoft support (http://support.microsoft.com/kb/240941):
Note that when the metabase is searched for configuration information,
it is enumerated from the bottom, or subkey, to top, or node.
This seems to imply that it does do what I think, but it's not 100% clear if it works on site Id as I'm not sure how this relates to the subkey.
The documentation does not specifically define the order as by site ID so it would not be safe to assume it will always be sorted that way (particularly as your current application eventually gets used with new versions of .NET/Windows/IIS in the future).
Most likely the number of websites is not going to be big enough that enumerating them to find the max would not be a bottleneck.
Even so, you can run a search for websites and specify the order using DirectorySearcher.Sort.
Note that in regards to your edit and how configuration information is enumerated, that does not related to sort order. The one sentence taken out of context is not as clear. Read it in context of the whole paragraph and it is clear that the enumeration behavior is related to metabase property inheritance.

How do I create an mvcsitemap that displays a dynamic name

Really struggling with this and not finding much helpful stuff on google.
I set up a sitemap, and I want some breadcrumbs such that url:
/CatManagement/Cats/38
displays breadcrumbs
Cat Management > Cats > Mr. Fuzzy Wuzzy
I don't quite understand what the sitemap node structure would be for this as the 38 is sort of a parameter of Cats.
In the dynamicNodeProvider I created I can probably grab the ID somehow and do a quick lookup to get the name, but I am not sure how to bring it all together.
Any ideas?
Have a look at Routing Basics in the MvcSiteMapProvider wiki. You just need to ensure that your parameter (38) is preserved from the current request, the node matching logic already takes into consideration action method parameters. That example shows how you would do that using a custom dynamic node provider, but I recommend reading the entire document as understanding it is key to making MvcSiteMapProvider work.
I have also created a more in depth look at the problem here with working demos for download: http://www.shiningtreasures.com/post/2013/09/02/how-to-make-mvcsitemapprovider-remember-a-user-position

ASP.NET MVC / C# - String to valid URL characters?

I don't know how to ask this, and I don't know what it is called either so I'll just describe what I want to achieve.
In the database, some articles' title originaly has spaces:
my title with spaces
But in the url, spaces are replaced by other characters such as plus sign (+) or underscore (_)
http://www.mydomain.com/mycontroller/myaction/my_title_with_spaces
or
http://www.mydomain.com/mycontroller/myaction/my+title+with+spaces
Now, how do you do that in C#? Or is there any helper in ASP.NET MVC that can do something like that?
Let say we achieved the said URL, is there any risk that two unique titles become the same in the URL? Please consider these titles:
Title's
Titles
after parsing, they became the same
Titles
Titles
This will be a problem when retrieving the article from the database since I'll get two results, one for "Title" and one for "Title's".
I would implement that functionality like this:
1. When creating a new article, generate the URL representation based on the title.
Use a function that converts the title for a suitable representation.
For example, the title "This is an example" might generate something like "This_is_an_example".
This is up to you. You can create a function that parses the title with rules you define, or use an existing one if it suits better your problem.
2. Ensure the URL representation is unique
If it's going to be an ID, it must be unique. So, when creating new articles you must query your database for the resulting URL representation. If you get a result from the database, it means the newly created article generated the same representation as one of the already created articles. Add something to it so it remains unique.
This could be something like "This_is_an_example_2". In this case, we added the "_2" to the end of the generated representation so it differs from the already existing one. Once more, with each change you have to ensure this representation remains unique.
3. Save the created ID in the database, along with the article data
In the database be sure to save the "This_is_an_example" ID and relate it to the article. Maybe even as the table primary key?
4. Query the database for the correct article
Now, about showing a site visitor the correct article:
When a visitor asks for the following resource, for example:
http://www.mydomain.com/mycontroller/myaction/this_is_an_example_2
Extract the URL part that identifies the article, in this case "this_is_an_example_2".
When you have that, you have the identifier of the article in the database. So, you can query the database for the article with the "this_is_an_example_2" ID and show the article's content to the user.
This might involve some URL rewriting. Unfortunately I'm unable to help you with that in asp.NET. Some search on the subject will surely help you.

Multiple Optional Parameters with ServiceStack.Net

I'm trying to implement a service with Multiple Optional Parameters using ServiceStack.Net
At the moment my route looks like this
Routes.Add<SaveWeek>("/save/{Year}/{Week}");
I want to support uris like this:
/save/2010/12/Monday/4/Tuesday/6/Wednesday/7
ie Monday=4, Tuesday=6 and Wednesday=7
However I want the ability to ignore days i.e. the person calling the service can decide if they want to save each value for each day...
i.e. Like this with missing parameter values
?Monday=4&Wednesday=7&Friday=6
Of course one solution would be to have the following route and just pass 0 when I don't want to save the value.
Routes.Add<SaveWeek>("/save/{Year}/{Week}/{Monday}/{Tuesday}}/{Weds}/{Thurs}/{Fri}/{Sat}/{Sun}");
But..... is there a better way of achieving this functionality?
When your Route requirements start to get too complicated it will eventually become easier just to add a wild card path so you can parse the rest of the querystring yourself. i.e. in this case since the first part of the querystring remains constant you can add a wild card mapping to store the variable parts of the querystring, i.e:
Routes.Add("/save/{Year}/{Week}/{DaysString*}");
ServiceStack will still populate the partial DTO with the Year and Week fields (as well any fields that were passed in the querystring). The remaining variable parts of the url is stored in the DaysString which you are then free to parse yourself manually. So the above mapping will be able to match urls like:
/save/2010/12/Monday/4/Tuesday/6?Wednesday=7
And populate the following variables in your Request DTO:
Year: 2010
Week: 12
Wednesday: 7
DaysString: Monday/4/Tuesday/6

ASP.Net MVC - route object id == title - how to deal with duplicates?

Web pages have moved to use URLs like:
//weblogs.asp.net/scottgu/archive/2007/12/03/asp-net-mvc-framework-part-2-url-routing.aspx
i.e. they include the title of the page in the url rather than having some coded id.
I understand that this is useful for SEO, and also for users in finding the correct page where they wish to type in the url.
I would like to follow this approach, but wonder how best to acheive it, and particularly how to deal with duplicates.
Is a database trigger which creates the url based on the title and adds a numeric incremental suffix to any duplicates the best way to go, and if so what would such a trigger look like?
Instead of having an id based on a title they could use id based on both a date and a title (2007/12/03/asp-net-mvc-framework-part-2-url-routing). So if you don't have articles with the same titles in one day (which isn't too severe restriction) duplicates are eliminated.
In Wordpress at least, the "slug" (as they call it) is generated once from the item's title and stored separately in the database. If two "slugs" collide, it appends -1, -2, etc. to the end. I personally prefer if you add an (optional) field to the submission form to allow people to insert their own—it allows people to specify a shorter URL than my-long-article-is-hard-to-type.
You've got to model this concept in your application. URL generation based on title can be automatic, but it can't be invisible. WordPress (and probably other CMS's, too) do a pretty good job of this -- they'll default a URL based on the information you enter, but the "key" part of the URL is visible and editable to the user, and uniqueness is enforced at the appropriate level (globally, per month, per day -- whatever).
Making URL generation completely invisible will lead to confusing errors for the user, I believe.
You could do the same thing that SO does. That is, the slug is only there as GoogleJuice. These two URLs resolve to the same thing:
ASP.Net MVC - route object id == title - how to deal with duplicates?
ASP.Net MVC - route object id == title - how to deal with duplicates?
So, in the example you gave, if the CMS gave each post a unique numeric identifier (which I suppose is quite likely) then you can include it in the URL:
http://weblogs.asp.net/scottgu/archive/2007/12/03/1234/asp-net-mvc-framework-part-2-url-routing
In this example, the symbol 1234 is the post's identifier.

Categories

Resources