I'm devloping a C#/ASP.Net app and I'm trying to find a means of breaking down a URL into its component parts, then swapping out, or deleting these parts and creating a new URL.
For example if I have the following URL:
https://www.site.com/page.aspx?parm1=value1&parm2=value2
I'd like to split the URL down into:
Protocol (http, https, ftp, etc)
Domain (www.site.com)
Page (page.aspx)
URL parameters (parm1 = value1, parm2 = value2)
Once the URL is split down I'd like to manipulate each of the parts, for example:
add or remove parameters
change the value of parameters
change the page from page.aspx to page2.aspx
Then once I'm done create a new URL ready for use with the above changes.
I've checked out the MSDN documentation etc and can't find a utility class in .Net to take care of this. Any ideas?
Cheers,
Steve
The framework comes with the UriBuilder class for this purpose.
It has get/set properties for the things you need:
Protocol: Scheme property
Domain: Host property
Page: Path property (will give you whole path, you might need to do some processing here).
Parameters: Query property (exposed as a string, you might need to do some processing on the string your self).
When you are done manipulating the UriBuilder, use the Uri property to get the result as a Uri object, or just ToString() if you just need the URL as a string.
Start by using UriBuilder (see driis's answer).
To parse the Query property use:
NameValueCollection q=HttpUtility.ParseQueryString(uri.Query);
You actually get an HttpValueCollection (internal) - so when you later call q.ToString() you'll get an url encoded query string back.
Since the class is internal you need to call
NameValueCollection q=HttpUtility.ParseQueryString("");
if you want to build the query string from scratch.
Related
I'm making an ecommerce application and I want the user to be able to put content at a URL they have specified. IF a user were to put in something like "/thank-you!", how can I clean the string to either be a valid URL or check this is valid URL format? I would want the url to basically always be hyphened between words so like "/thank-you" from "/thankyou". What's the best approach for achieving such a thing. I'm within c# using .NET MVC 4.
Alas, I cannot comment 'possible duplicate' yet (How to check whether a string is a valid HTTP URL?).
As this must be an answer however, one way to validate a string URL would be using the URI.TryCreate functioanlity. See here also https://msdn.microsoft.com/en-us/library/system.uri.trycreate(v=vs.110).aspx
URI is also the preferred data type for URLs, rather than strings.
I'm using Grapevine and I want to route request traffic that has a query string, and I don't know regular expressions well enough to figure out why it's not working.
e.g.
http://localhost:1234/service/function?param1=1¶m2=2
And I defined my RESTRoute like this:
[RESTRoute(Method = HttpMethod.GET, PathInfo = #"^/service/function\?\D+$")]
public void HandleFooRequestString(HttpListenerContext context)
{
PrintRequest(context);
this.SendTextResponse(context, "foo is a success!");
}
But traffic sent to the URL isn't going to that method. What am I doing wrong?
This is a pretty common question, and has spawned some changes to the Grapevine road map.
Grapevine 3.1.0 +
In the most recent version of Grapevine, the query string is stripped off of the URL prior to regular expression pattern matching, so this is no longer a problem.
Additionally, routing is being updated in version 4 to match the Node/Express routing mechanism, so you can opt to not use regular expressions at all if you prefer. However, this version is still in the planning stages.
Grapevine 3.0.x
While it certainly isn't uncommon for GET requests to contain query string parameters, let's first make sure we are using proper URI design. To quote from O'Reilly's RESTful Web Services, page 233, under the header URI Design (emphasis mine):
When designing URIs, use path variables to separate elements of a hierarchy, or a path through a directed graph. Example: /weblogs/myweblog/entries/100 goes from the general to the specific. From a list of weblogs, to a particular weblog, to the entries in that weblog, to a particular entry. Each path variable is in some sense "inside" the previous one.
Use punctuation characters to separate multiple pieces of data at the same level of hierarchy. Use commas when the order of the items matters, as it does in latitude and longitude: /Earth/37.0,-95.2. Use semicolons when the order doesn't matter: /color-blends/red;blue.
Use query variables only to suggest arguments being plugged into an algorithm, or when the other two techniques fail. If two URIs differ only in their query variables, it implies that they're the different sets of inputs into the same underlying algorithm.
The big takeaway here is that our URIs, generally speaking, should only use the query string to pass arguments to an algorithm. If, indeed, we are expecting query string parameters in our methods, those should be validated by the method the request is routed to, and our PathInfo regular expressions should reflect the possibility of receiving such arguments.
Example: When not to use query string
Suppose you wanted to request user data given a specific numeric user id, let's say 632. This is a scenario where it might be tempting to use the query string, but it would be better not to.
Less Correct URI: /user?id=632
More Correct URI: /user/632
The RESTRoute for the more-correct URI would then look like this:
[RESTRoute(Method = HttpMethod.GET, PathInfo = #"^/user/\d+$")]
public void GetUser(HttpListenerContext context)
{
var userid = context.RawUrl.GrabFirst(#"^/user/(\d+)$");
// you got your user id, do something
}
Example: Correctly using the query string
If you wanted to create a REST route that multiplied two integers together, then - setting aside that URI are suppose to represent resources, not operations on a resource - using a query string might be more suitable.
Probably Less Correct URI: /2/product/3
Probably More Correct URI: /product?x=2&y=3
The RESTRoute for the probably-more-correct URI would then look like this:
[RESTRoute(Method = HttpMethod.GET, PathInfo = #"^/product")]
public void MultiplyTwoIntegers(HttpListenerContext context)
{
var x = context.Request.QueryString["x"];
var y = context.Request.QueryString["y"];
// Verify the inputs and do the math.
}
Note that the PathInfo regular expression omits the trailing $, which would normally indicate the end of the string, and we let the route method handle getting the parameters passed. If we really wanted to be a stickler, we could also write it like this:
[RESTRoute(Method = HttpMethod.GET, PathInfo = #"^/product\?.+$")]
Which would ensure that it at least looked like there might be some parameters coming in the query string, but isn't really necessary since we are going to do that checking anyway.
I got a URL which contains parameters, one of which is with Cyrillic letters.
http://localhost/Print.aspx?id=4&subwebid=243572&docnumber=%u0417%u041f005637-1&deliverypoint=4630013519990
Doc-number must be ЗП005637-1.
I have tried the following code, but string is still with those characters %u0417%u041f.
public static String DecodeUrlString(this String url)
{
String newUrl;
while ((newUrl = Uri.UnescapeDataString(url)) != url)
url = newUrl;
return newUrl;
}
It's not a possibility to use HttpUtility.
If your goal is to avoid a dependency on System.Web.dll, then you would normally use the equivalent method in the WebUtility Class: WebUtility.UrlDecode Method.
However, you will find that, even then, your url won't get decoded the way you want it to.
This is because WebUtility.UrlDecode does not handle the %uNNNN escape notation on purpose. Notice this comment in the source code:
// *** Source: alm/tfs_core/Framework/Common/UriUtility/HttpUtility.cs
// This specific code was copied from above ASP.NET codebase.
// Changes done - Removed the logic to handle %Uxxxx as it is not standards compliant.
As stated in the comment, the %uNNNN escape format is not standard compliant and should be avoided if possible. You can find more info on this and on the proper way of encoding urls from this thread.
If you have any control over how the url is generated, consider changing it to be standard-compliant. Otherwise, consider adding System.Web.dll as a dependency, find another third-party library that does the job, or write your own decoder. As commented already, the source code is out there.
I have a route in controller that should match everything in part of url and put it into string parameter.
What I have is:
[Route("api/proxy/{proxyId}/{*parameter}")]
public Task<HttpResponseMessage> Mediate(int proxyId, string parameter)
and for an unknown url, for example:
http://localhost/api/proxy/1/test?a=1&b=2
I would like "parameter" variable to contain:
test?a=1&b=2
Instead, it contains:
test
How can I specify route to not cut everything after question mark?
For this particular case I can extract it from Request.RequestUri object, but it would be.. inelegant.
You cannot do that. By definition the URL segments doesn't include the query string.
However, you can do something really easy: inside your WebApi controller you have the Request property which contains the Query String:
Request.RequestUri.Query
You simply have to concatenate the url param with this to have what you need. This includes the leading question mark:
The Query property contains any query information included in the URI. Query information is separated from the path information by a question mark (?) and continues to the end of the URI. The query information returned includes the leading question mark.
from Uri.Query Property
If you still want to force it to work in a different way, you'd need to include your own custom route provider, implementeing your own IDirectRouteProvider and registering it. See this: get a list of attribute route templates asp.net webapi 2.2
But doing something like this is unnatural. Why do things exactly in a different way as the standard way that all other people aunderstand and use?
I have a situation where I need to put a url inside a GET variable.
for example:
'http://www.site.com/StepOne?b=1&afterUrl=http://www.site.com/StepTwo?someVar=text&b=1'
In this case, when I am at StepOne the b param value will be 1,1 and not 1 as expected.
the afterUrl param will be:
'http://www.site.com/StepTwo?someVar=text'
instead of this:
'http://www.site.com/StepTwo?someVar=text&b=1'
How do I isolate the afterUrl param so its own GET variables won't effect the entire URL.
When you are creating the afterUrl URL parameter, be sure to UrlEncode() the value.
e.g.
var url = String.Format("http://www.site.com/StepOne?b={0}&afterUrl={1}", b, Server.UrlEncode(afterUrl));
Consider using HttpUtility.UrlEncode() for the AfterURL
(EDIT or Server.URLEncode() as others have pointed out)
"http://www.site.com/StepOne?b=1&afterUrl=" +
HttpUtility.UrlEncode(http://www.site.com/StepTwo?someVar=text&b=1");
Then when you finally hit the "StepOne" page you can use HttpUtility.UrlDecode(AfterURL variable name). From there you can Response.redirect or whatever you want with the preserved after url.
Use Server.UrlEncode on someVar to escape out it's querystring values before putting it in the link. You may need to use Server.UrlDecode on the other side to convert it back to the original characters.
Quite simply, you need to URL encode the afterUrl param (actually, you should URL encode all parameters passed to a server), which will turn "http://www.site.com/StepTwo?someVar=text&b=1" into "http%3A%2F%2Fwww.site.com%2FStepTwo%3FsomeVar%3Dtext%26b%3D1", which won't affect the set of parameters. Almost any server framework on the market will automatically decode that back into the string "http://www.site.com/StepTwo?someVar=text&b=1", or at least give you a function to do so yourself.
EDIT:
As this SO question shows, it is possible to URL encode a string without using System.Web, using System.Net.Uri.EscapeDataString().