Get the full QueryString from URL in ASP.NET - asp.net

I have an URL with the following format:
http://www.mysite.com/login.aspx?ref=~/Module/MyPage.aspx?par=1&par2=hello&par3=7
I use the content of the QueryString it to Redirect the user back to the page he was before logging in. In order to keep also the status of the page I need the parameters in the QueryString. The number of parameters changes depending on the Page calling the Login and its status.
Let's say I want to store everything in the URL after ref in the redirectURL variable. I tried:
redirectURL = Request.QueryString("ref") // "~/Module/MyPage.aspx?par=1"
it gets everything after ref but ignores everything after the &(included). If I use:
redirectURL =Request.Url.Query // "ref=~/Module/MyPage.aspx?par=1&par2=hello&par3=7"
it gets everything, ref included. In order to achieve my goal I need just to remove the first 4 characters from the redirectURL. But I think this solution is a bit "forced" and I am sure there should be some ASP.NET function that accomplish this task.

The &s in your URL are creating additional querystring arguments.
You need to escape the value of the ref parameter before putting it in the querystring.
This will replace the &s with %26.
To do this, call Uri.EscapeDataString().
When you fetch the property from Request.QueryString, it will automatically decode it.

Consider Encoding "~/Module/MyPage.aspx?par=1&par2=hello&par3=7" before passing it to the url.
Eg.:
String MyURL = "http://www.mysite.com/login.aspx?ref=" +
Server.UrlEncode("~/Module/MyPage.aspx?par=1&par2=hello&par3=7");
And then, you can get the redirectURL using:
String redirectURL = Request.QueryString("ref");

Related

returnUrl drops second querystring parameter

I am using MVC 5. The problem is that after SSO redirects back to the app after authentication the login method returnUrl drops the applicaitonId querystring parameter. Please help!
Here is the flow.
The app redirects unauthorized users to a login method, preserving the original request in the returnUrl.
The original request is
http://localhost:25451/shared/download?documentGroup=133&applicationId=3153
the returnUrl is
/shared/download?documentGroup=133&applicationId=3153
The app redirects to a SSO CAS server, sending along the HttpUtility.Encode returnUrl as a parameter along with login Url both part of the service parameters.
https://{redacted}/cas/login?service=http://localhost:25451/account/login%3freturnUrl%3d%2fshared%2fdownload%3fdocumentGroup%3d133%26applicationId%3d3153
After authentication, the CAS server appends the authorized ticket and redirects back to the service URL. This is what fiddler shows.
http://localhost:25451/account/login?returnUrl=/shared/download?documentGroup=133&applicationId=3153&ticket={redacted}
Here is the issue. The returnuRL in the login method is simply
/shared/download?documentGroup=133.
The returnUrl no longer has the applicationId.
Interestingly enough, the line works just fine.
var ticket = Request.QueryString.Get("ticket");
I have tried to encode the whole serviceUrl and tried to encode just the returnUrl(see below) but I get the same missing ApplicationId issue.
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
var ticket = Request.QueryString.Get("ticket");
if (!string.IsNullOrEmpty(ticket))
{
//verify the ticket...
return RedirectToLocal(returnUrl);
}
var serviceUrl = Request.Url.Scheme + System.Uri.SchemeDelimiter + Request.Url.Host + (Request.Url.IsDefaultPort ? "" : ":" + Request.Url.Port) + "/account/login" + "?returnUrl=" + HttpUtility.UrlEncode(returnUrl);
var authenCasUrl = string.Format("{0}login?service={1}", "https://{redacted}/", serviceUrl);
return Redirect(authenCasUrl);
}
Since this site will be actually called by your URL, I don't think they just throw away parts of it.
Lets try something here since I have encountered a similar problem with parameter in url strings in combination with asp.NET.
First, lets get the unedited URL from your Request:
string UneditedUrl = Request.RawUrl;
Since we are not needing anything before the ? mark, we shorten it a little bit:
string QueryString = (UneditedUrl.IndexOf('?') < UneditedUrl.Length - 1) ? UneditedUrl.Substring(UneditedUrl.IndexOf('?') + 1) : String.Empty;
This line also includes the possibility on neither having a ? mark or parameters and will return an empty string if so. Just for good measure, we don't want any exceptions here. Here you can check QueryString if it has both or more of your parameters you entered.
If there are not complete here, its not your code at fault. Something will already work on your URL before you do, probably your host then. Maybe check the settings of your IIS.
If your parameters are correctly in the edited QueryString, you can continue getting them by following this:
I learned that there is a way to let your framework do the job of parsing parameters into name/value collections. So lets give it a go:
NameValueCollection ParaCollection = HttpUtility.ParseQueryString(QueryString);
You can now check you params and their values by either using an index like ParaCollection[0] or ParaCollection["documentGroup"].
EDIT:
I've found the question which brought me to the conclusion of using Request.RawUrl. Since this may not be the answer, it will maybe help a little bit more to understand that Request.RawUrl is the actual URL the user called and not the one the server executes: RawURL vs URL
I have no experience with asp or SSO, but you may need to also HttpUtility.UrlEncode the value of the serviceUrl variable?
var authenCasUrl = string.Format("{0}login?service={1}", "https://{redacted}/", HttpUtility.UrlEncode(serviceUrl));
Since the service parameter is decoded by the CAS once, and then the value of returnUrl gets decoded by your server.
var returnUrl = "/shared/download?documentGroup=133&applicationId=3153";
var serviceUrl = "http://localhost:25451/account/login?returnUrl=" + HttpUtility.UrlEncode(returnUrl);
var casUrl = "https://{redacted}/cas/login?service=" + HttpUtility.UrlEncode(serviceUrl);
Which gives:
serviceUrl = http://localhost:25451/account/login?returnUrl=%2Fshared%2Fdownload%3FdocumentGroup%3D133%26applicationId%3D3153
casUrl = https://{redacted}/cas/login?service=http%3A%2F%2Flocalhost%3A25451%2Faccount%2Flogin%3FreturnUrl%3D%252Fshared%252Fdownload%253FdocumentGroup%253D133%2526applicationId%253D3153
Explanation attempt:
You make a HTTP request to the CAS server. It's implementation splits the query parameters and decodes each value (and possibly key). One of which is the service parameter and is now (after decoding) a valid URL.
The CAS server makes a HTTP request with the URL from the service parameter (to your server) with the ticket appended.
You split the query parameters and decode each value (and possibly key).
If you only encoded the returnUrl once, your serviceUrl will look like what you showed in your third point:
http://localhost:25451/account/login?returnUrl=/shared/download?documentGroup=133&applicationId=3153&ticket={redacted}
How does the algorithm splitting the query string differentiate between a ? or & in the serviceUrl and the ones in the returnUrl?
How should it know that ticket does not belong to the returnUrl?
As you can see in my code above, you are not encoding the returnUrl twice.
You are putting one URL in the parameters of another URL and then you put that URL in the parameters of a third URL.
You need to call UrlEncode for each value (and possibly key) when you put together a query. It does not matter whether that value is a URL, JSON, or arbitrary user input.

ASP.Net WebForms malformed querystring, ? rather than &

In one of our webforms apps we have external links coming to the site where there are 2 querystring parameters, but the second param is also preceded by a ?.
Normally, your querystring will only have one ?, which is at the beginning just before the first param, and any subsequent params are preceded by &. For example:
www.somesite.com?param1=a&param2=b <---- this is properly formed
www.somesite.com?param1=a?param2=b <---- this is malformed
Yes, I know that param values can contain question marks, and it is best to escape them, but we don't have that issue.
These urls are coming from an external source and we can't do anything about them right now, but we do need to parse the querystrings properly.
With the above malformed url, Request.QueryString["param1"] yields:
a?param2=b
But if the url were properly formed it would yield:
a
Also if properly formed, Request.QueryString["param2"] would yield:
b
How best to handle such a situation, if you are unable to fix the source of the problem? I might add that the url comes to the site urlencoded.
This is the solution that I have come up with. Just fix the querystring and redirect back. In the Page_Load, I call this ProcessQS method, and have added the fix qs code to it:
private bool ProcessQS()
{
var param1 = Request.QueryString["param1"];
if (string.IsNullOrWhiteSpace(param1))
return false;
// Workaround for external links that have ? instead of & for querystring parameter beyond the first.
// In this case, id should be preceded by &, this handles those urls that have a ? preceding id.
if (param1.Contains("?param2="))
{
var qs = Request.ServerVariables["QUERY_STRING"];
qs = HttpUtility.UrlDecode(qs);
Response.Redirect($"~/somepage.aspx?{qs.Replace("?param2=", "&param2=")}", true);
}
return true;
}

how to forward a link with URI to another link with the same URI

My program directs users to a webpage with their username and password. E.g.
http://example.html?username=username&password=password.
Now I created another page in asp.net and I want some code on example.html to redirect the link to http://example.aspx?username=username&password=password.
So what i want is to get the URI from the first url and direct it to the new url by appending the URI.
Any suggestions?
You can grab the querystring in its entirety via
window.location.search
See this with more about that. Using this, you can extract the parameters, append them to a new URL, and render the link, or set
window.location = "example.aspx" + window.location.search
I believe search comes with "?", but I could be wrong. I assume this is an exmaple; note it's not a good practice to pass the password through a querystring as clear text, especially if you are not using HTTPS. It's generally advisable to do a POST operation, not a GET operation with querystring, when it comes to sensitive information.
Use window.location.search to get everything after "?". Then you can just direct the new aspx page using this java script line.
window.location = "example.aspx" + window.location.search

what is the difference between rawurl and query string?

i read about httphandler and they use rawurl and then they said :
For example, suppose you rewrote the HTTP handler that processes image requests so that
it is based on the query string instead of the file name
When you make a url rewrite the Request.RawUrl is shown the url that user see on the bar, there you do not have the query strings that you have rewrite.
For example if you rewrite the www.site.com/2/product to www.site.com/product.aspx?id=2 to been able to read the id you need to use the Query string, because the RawUrl did not have it.
HttpRequest.RawUrl Property Gets the raw URL of the current request.
see more http://msdn.microsoft.com/en-us/library/system.web.httprequest.rawurl(v=vs.110).aspx
html addresses use QueryString property to pass values between pages
http://www.localhost.com/Webform2.aspx?name=Atilla&lastName=Ozgur
Webform2.aspx this is the page your browser will go.
name=Atilla you send a name variable which is set to Atilla
lastName=Ozgur you send a lastName variable which is set to Ozgur

MVC3 Stripping Query String from my Parameter

I have an MVC3 Action that takes a parameter (a URL) that may have a query string in it. My action signature looks like this:
GetUrl(string url)
I expect to be able to send it urls, and it works every time unless there is a query string in the url. For example, if I navigate to:
MyController/GetUrl/www.google.com
the url parameter comes accross as "www.google.com" -Perfect. However, if I send
MyController/GetUrl/www.google.com/?id=3
the url parameter comes accross as "www.google.com/" How do I get MVC3 to give me the whole URL in that parameter? -Including the query string?
It's simple enough to just URL.Encode the passed in URL on the page but you're opening your self to some possible security problems.
I would suggest you encrypt the url then encode it then pass that as your value, the protects you from having people just passing in anything into your app.
That's because system considers id=3 as its own query string. When you construct the link in the view, you need to use #Url.Encode to convert raw url string to encoded string to be accepted as parameter of the controller.

Resources