I have a route like this
/api/service/:id
But id is a string like name.of.something
So the the url will look like:
/api/service/name.of.something?other=parameters
The controller can't parse that request correctly because of dots.
How should I decode the id to pass it to the route?
You need to add a constraints option to the route that will cause it to accept periods. Note that this will break Rails' automatic format detection, so you will have to pass an explicit ?format=json to the URL if you specifically need format selection.
get "api/service/:id", to: "some#endpoint", constraints: {id: /[[:alnum:]_\.-]+/i}
Adjust the regex to your preference.
Related
Suppose I am expecting a url as part of my route - maybe a callback url or similar - I might use the following route:
get '/mymodel/:url', to: 'mycontroller#docallback', url: /.*/
Now I would like to be able to go to http://www.myapp.com/mymodel/http://www.google.co.uk/ and process http://www.google.co.uk/ in mycontroller - but it is processed as http:/www.google.co.uk/ (one slash). How can I rectify this? Is the regex wrong or is there some flag I have to set?
I don't think that "http://www.myapp.com/mymodel/http://www.google.co.uk/" is a valid url.
Normally if you want to pass a url as a parameter you would call CGI.escape on it first, which would convert "http://www.google.co.uk/" to "http%3A%2F%2Fwww.google.co.uk%2F" CGI.escape will turn any string into a url-safe version of itself, basically replacing any characters which have a special function in a url, like ":/?&" and also space and some other characters which would otherwise break the formatting.
So, you would end up with a url like
"http://www.myapp.com/mymodel/http%3A%2F%2Fwww.google.co.uk%2F"
which would come through in params like
params = {:url => "http://www.google.co.uk/"}
Note how it's been unescaped here: Rails automatically* calls CGI.unescape on parameter values before putting them into the params hash.
However, this url
"http://www.myapp.com/mymodel/http%3A%2F%2Fwww.google.co.uk%2F"
looks pretty weird to me. It would be better to be more explicit and pass it through as a named parameter in the url itself, like
"http://www.myapp.com/mymodel?url=http%3A%2F%2Fwww.google.co.uk%2F"
which will require a slight change to your routes.
* I think Rails will do this but it might depend on circumstances. Try it.
...Turned out that the request was not encoded on the client side before being sent, solution was to use encodeURIComponent() on the url before sending it.
I'm using AnchorLink on a very simple site with just two routes defined, one standard route and another area route for admin/{controller}/{action}/{id}. I'm at a URL like:
/admin/release/push/255
In that view I'm using:
#Html.AnchorLink("Confirm", "Confirm")
AnchorLink is rendering a link without the current request {id} included, ie. /admin/release/confirm! If I inspect the RouteValues I can see {id} is in there. If I explicity pass in the route values from teh current request, as in:
#Html.AnchorLink("Confirm this release", "Confirm", Url.RequestContext.RouteData.Values)
Then it works, I get the URL /admin/release/confirm/255. Why does the explicit version where I pass in the current request route values work, but the implicit one, without the route values argument, which I thought would pick up the current request route values, doesn't? I know the above is a solution, but it's ugly and there's some underlying reason why the AnchorLink without the route values isn't working as I expect?!
MVC is doing exactly the right thing here. It's not to know you require the Id parameter for your anchor link or not -- in other words its not trying anything clever to pre-parse and examine the link. It will only do that when its being rendered. And in your case without the id parameter specified somewhere its going to use the default route.
If you find yourself writing that same code all over the place you could easily extract it out into a static helper class. That can get rid of the ugliness.
This is kind of strange.
I have a route:
match "program/:program_id" => "program#details"
When calling this, everything works:
/program/1
However, the program IDs I use aren't digits only. They're in fact URLs like so: crid://blah.com/d1e5
How can I pass an URL via a RESTful approach as a paramter?
Calling this doesn't work, obviously:
/program/crid://blah.com/d1e5
/program/crid%3A%2F%2Fblah.com%2Fd1e5
Use program/*program_id instead of program/:program_id.
RFC 1738 says:
... only alphanumerics, the special characters "$-_.+!*'(),", and reserved characters used for their reserved purposes may be used unencoded within a URL.
So if you are trying to put a URL into the URL, you will either have to put up with the encoded characters because the colon : is not an allowed character except as the protocol seperator, and because a double slash // is not allowed except at the root of the URL, or you have to drop the protocol and the root from your URL and start with the domain. That is:
You can either do this:
/program/crid%3A%2F%2Fblah.com%2Fd1e5
or this
/program/blah.com/d1e5
A compromise when using Rails could be putting the protocol into a URL segment like so:
/program/crid/blah.com/d1e5
which you can collect in your params array with
match "program/:protocol/*program_id" => "program#details
The *program_id segment collects(globs) the rest of the url into a single entry in the params array.
you can recombine this in your controller if needed:
url = "#{params[:protocol]://#{params[:program_id]}}"
so that:
# GET /program/crid/blah.com/d1e5
params[:protocol] #=> "crid"
params[:program_id] #=> "blah.com/d1e5"
url = "#{params[:protocol]://#{params[:program_id]}}"
#=> "crid://blah.com/d1e5"
I am facing a problem that one of my fields need to be shown in the url contains special character (/, \, :).
The stupid way to handle this generate action links by using UrlEncode(). Then UrlDecode is used before consuming in controller. But I think it really stupid because too many places need to be adapted.
So, my problem is there any way to extend the url route or just write my own one to achieve it?
Thanks,
Mike
You can extend the System.Web.Routing.Route object to create a custom route and override the GetRouteData and GetVirtualPath methods. These are called to resolve a route's values and create a URL from given route values, respectively. However, I don't think URLs can contain URL encoded values for / (%2f) within the path portion of a URL though it is ok in a query string.
Can anyone tell me what is the syntax for retreiving the actual URL for the "Default" Route?
I'd like to do something like:
string url = RouteTable.Routes["Default"].ToString();
//(even though that code is completely wrong)
so that I could have the url value of the route available to work with.
So far, I've been trying the .GetVirtualPath() method, but that only returns the route data for the current controller.
thanks
Dave
A route can match any number of urls. So a route doesn't have a url. To get a url from a route you will have to supply it with the route data that you want the url for. To do that you simply use the RouteUrl() method on the Url property, Url.RouteUrl().
Update
If you want the url that will be generated if you supply the route with its default values you can do something like this:
var url = Url.RouteUrl("Default", ((Route)RouteTable.Routes["Default"]).Defaults);