Our webform (ProcessStudent.aspx) is designed to receive three parameters in the QueryString: Name, Grade, Class. Page_Load retrieves these three parameters and sends it to a method SaveStudent (ie. SaveStudent(name, grade, class);).
I need to process several three-parameter combinations for one page. I basically copied/pasted ProcessStudent.aspx, but I need to modify the way I read the parameters. I can change the URL structure, but everything else needs to stay the same.
So my initial thought was to include these combinations in the URL; for example, each value would be separated by a char and each combination by another char. Something like this, which I would then parse :
ProcessStudent.aspx?Students=Joe|5|Science,Bob|6|Math,Mary|5|English
Would something like this work? Is there a better way?
Yes it would work. As far as better... You could post a json string, which would be much cleaner. I personally would use a rest service with just JSON(or XML if you like).
Hope this helps.
The thing you'll need to watch out for is that the query string has a length limit in some browsers (https://stackoverflow.com/a/812962/97382) so depending how many you mean by "several" and which browser(s) you're using you could run into those limitations.
You would be better off to POST the data as you do not run into the size limitations.
Related
I need to pass multiple values as one param in the query string. Is there a better way to do it than the below example? I do not want to use session to send these values from page to page.
For example: http://www.mywebapp.com/Products.aspx?CategoryIds=45|29|98
Is pipes the best way to do something like this? I noticed they get turned into % symbols but it does not mess up my code when I do:
Request["CategoryIds"];
I had the similar situation and I am using comma to separate the numbers in query string.
Even in your case, looks like the CategoryIds are all numbers. So, I think comma should work for you.
And the URL will look something like this: http://localhost:62100/Contact.aspx?CategoryIds=1,2,3
What I'm trying to do is use an UriBuilder and HttpUtility.ParseQueryString to get the last page the user visited and then parse the URL to get just the productID. (The product ID is different on each page if that matters)
example URL: website.com/stuff/?referrerPage=1&productID=1234567&tab=Tile
and what I want is just the 1234567
Page_Load is where I parse the URL:
protected void Page_Load(object sender, EventArgs e)
{
NameValueCollection query = HttpUtility.ParseQueryString(uriBuilder.Query);
//I want to take the parse string and get productID here, how?
}
grabURL is where I get the last URL visited:
public grabUrl(string Uri)
{
UriBuilder uriBuilder = new UriBuilder(Request.UrlReferrer);
return uriBuilder.Uri;
}
Am I on the right track with my code? How do I put the productID number in something so I can work with it? I'm very new to c# and this type of coding in general... when I say new I mean I've been doing it for about a week. So any detailed explanations or examples will be very much appriciated. Thanks everyone for being so helpful, I'm learning a lot from this site to get me on the right track.
From a NameValueCollection you can then do:
var id = query["ProductID"];
You can use int.TryParse to turn it into an integer proper.
int id = 0;
if (!string.IsNullOrEmpty(query["ProductID"]) &&
int.TryParse(query["ProductID"], out id)) {
// use id here..
}
Or you could just request the querystring value from your URL using Request.QueryString()
protected void Page_Load()
{
//save yourself the conversion to int and just save it as Int if you know for sure
// it will always be int
int _prodID= Request.Querystring["productID"];
//validate _prodID
if (!string.IsNullOrEmpty(_prodID.toString())) {//do something }
}
Could you use a regex to parse it instead?
string uri = "website.com/stuff/?referrerPage=1&productID=1234567&tab=Tile";
var rgx = new Regex("productID=(?<pid>[0-9]+)", RegexOptions.IgnoreCase);
string pid = rgx.Match(uri).Groups[1].Value;
Edit: Providing context as it has been suggested I should do:
The reason for mentioning this option is that while it doesn't use HttpUtility.ParseQueryString, your original question was very specific:
get just the productID
from
the last page the user visited
(which I understand to not be the uri of the current request). Additionally you provided the Uri was provided in a string format.
The approach in your question does this:
Takes Uri (a string variable)
Passes it to UriBuilder; UriBuilder in its constructor initialises a Uri, which itself does a ton of work to validate the uri, populate properties etc. by creating more strings, among other things
Then, from the Uri object generated, you now work with the Query property - this is one of the new strings that Uri has allocated
Passes that to HttpUtility.ParseQueryString. This creates a HttpValueCollection, which itself iterates character-by-character over the string you pass in to parse out the key-value pairs in the query string, and sticks them into a NameValueCollection, which ultimately stores your values in an ArrayList - one of the least efficient collections in .NET (see various references including this one - What's Wrong with an ArrayList?) as it stores everything in an object array, requiring casting every time you get things back out.
finally you then go and search that collection by a key to get your product id back out.
That's a whole lot of string and character allocations, casting to and from objects, putting things into indexed arrays which you then scan, etc. just to get:
a string which is identifiable by a pattern from another string.
While I admit that memory is cheap, it seems that there might be an equally good, or better, alternative. This is what regex was made for - find a pattern in a string, and allow you to get parts of that pattern back out.
So, your options:
If you just want to get productID out of a uri in an exact form, and the uri is originally in a string, then I maintain that a regex is a very good, efficient choice. This will also work if you want to extract other patterns from your uri.
If you want to know all the keys in your query string as well as values for specific keys, then use your HttpUtility.ParseQueryString approach; NameValueCollection allows you to get access to the keys through the AllKeys property.
If you want to get the value of a query string parameter for the uri of your current request then Marcianin's answer is the simplest choice, and you can forget the first 2 options.
In all cases, once you have the string you can parse it using the parse methods on int, but if you use 2. or 3. your extracted id may not be a number (in the case of a malicious request) so make sure you use int.TryParse not int.Parse to convert from a string, and be careful to catch exceptions. You should always take care when taking input from query strings so as not to fall foul of malicious data in the query string (which will hit your website frequently once it is online).
The choice is personal preference.
The actual code you write is about the same - each approach takes up very few lines.
Code should never prematurely optimise, but it should also not be deliberately wasteful if it can help it. You could performance test one against the other, but that would be a waste of your time at this stage.
However, code should also convey intent. The Regex approach, even I would argue, doesn't convey your intent as well as the ParseQueryString approach.
Footnote: I would change the regex slightly to "[?&]productID=(?<pid>[0-9]+)" to ensure you pick up only "productID" and not "fooProductID"
Most importantly, you asked
Am I on the right track with my code?
I would say you are. Always weigh up different options as you proceed. Don't be afraid to try different things out. You say you are new to C#. The one thing you may have missed, in this case, is writing a test to help you on your way before you wrote your code: if the test passes, the code is correct, and the approach you chose is secondary to that. Visual Studio makes testing easy for you if you are using the latest version. If you get into good habits early on, it will pay dividends later on in your C# career.
How do I put the productID number in something so I can work with it?
Grant Thomas answered this perfectly - int.TryParse turns the string into a number.
After reviewing the code below, I noticed that the call to Context.RewritePath is somehow not losing the query string, even though it is being called without a query string. Is there any documentation explaining why the query string is being maintained?
//URL relative path to ashx files is wrong to to path rewriting.
if (Request.Url.LocalPath.EndsWith(".ashx")) {
Context.RewritePath(Request.Url.LocalPath
.Substring(Request.Url.LocalPath.LastIndexOf("/") + 1));
}
Edit: I am not asking how to fix this; the code behaves correctly. I am just asking for documentation of this behavior.
You're essentially doing a Rewrite of the path, and in most cases, the query needs to be maintained to pass to the new Path.
Take for example a new document retrieval page named "getDocumentWithEnhancements.aspx" as opposed to the old "getDocument.aspx". Both need a parameter to be useful, but you want the new one to be used. A RewritePath would do the job, as it takes the query passed to the old, and passes to the new. If you want to show some sort of error page or something, then instead you'd either use a redirect, or whatever page you're rewriting to will just ignore the querystring.
Why would you not want the query to be passed through? What exactly are you using this for? Maybe it's not the right function for what you need.
edit: There's an overloaded function taking 3 parameters, one of which is a querystring, which you could pass in as null to not use the querystring.
I am wondering if anyone can help me out with parsing out data for key words.
say I am looking for this keyword: My Example Yo (this is one of many keywords)
I have data like this
MY EXAMPLE YO #108
my-example-yo #108
my-example #108
MY Example #108
This is just a few combinations. There could be words or number is front of these sentences, there could be in any case, maybe nothing comes after it maybe like the above example something comes after it.
A few ideas came to mind.
store all combinations that I can possible think of in my database then use contains
The downside with this is I going a huge database table with every combination of everything thing I need to find. I then will have to load the data into memory(through nhibernate and check every combination). I am trying to determine what category to use based on keyword and they can upload thousands of rows to check for.
Even if I load subsets and look through them I still picture this will be slow.
Remove all special characters and make single spaces and ignore case and try to use regex to see how much of the keyword matches up.
Not sure what to do if the keyword has special characters like dashes and such.
I know I will not get every combination out there but I want to try get as many as I can.
Have you considered Lucene.Net? I haven't used it myself, but I hear it's a great tool for full text searching. It might do well with keyword searching too. I believe that stackoverflow uses Lucene.
I'm posting to a web page which I was told took XML as it's body. Turns out that what it really requires is what looks like a URL encoded CGI query string:
<FIRST>
<ELEMENT1>Value1</ELEMENT1>
<ELEMENT2>Value1</ELEMENT2>
<ELEMENT3>Value1</ELEMENT3>
</FIRST>
<SECOND>
<ELEMENT1>Value1</ELEMENT1>
<ELEMENT2>Value1</ELEMENT2>
</SECOND>
Needs to be transmitted as
FIRST_ELEMENT1=VALUE1&FIRST_ELEMENT2=VALUE2&FIRST_ELEMENT3=VALUE3&SECOND_ELEMENT1=VALUE1&SECOND_ELEMENT2=VALUE2
The third party tells me this is a common usage, although I've not seen it before (as a method of submitting XML) it's obvious that the service was designed to take an HTML POST with a form as the source of data.
While I can see how I could write a transform I'm wondering if there is a mthod in the .Net framwork which achieves this translation. Upto and including .Net 3.5 is available on this project.
Thanks in advance
Dave
I've never seen that usage, but something like:
var query = string.Join("&",(
from parent in XElement.Parse(xml).Elements()
from child in parent.Elements()
select HttpUtility.UrlEncode(parent.Name.LocalName) + "_"
+ HttpUtility.UrlEncode(child.Name.LocalName) + "="
+ HttpUtility.UrlEncode(child.Value)).ToArray());
I strongly doubt there's anything built-in to achieve this, but coding it up shouldn't be hard. I'd use a recursive method that examines the children of a node, calling itself with a string prefix that represents the position of the node in the tree. Maintain a List or a Dictionary or whatever best suits your needs outside of the method and when you encounter a node with text data, append the prefix+tag and the value to your list. Then it'll be trivial to go through that list and join them in the querystring format. Take care to escape ampersands and other reserved characters, though.
That seems pretty crazy, I hope your XML data isn't very long... you're likely to run into issues if the querystring ends up too long.
I don't understand why you can't do an HTTP-POST , set the content-type to 'text/xml', and simply post the raw XML data.