HTTPServletRequest getParameterMap() vs getParameterNames - servlets

HTTPServletRequest req, has a method getParameterMap() but, the values return a String[] instead of String, for post data as
name=Marry&lastName=John&Age=20.
I see in the post data it's not an array, but getParameterMap() returns array for every key(name or lastName or Age). Any pointers on understanding this in a better way?
The code is available in Approach 2. Approach 1 works completely fine.
Approach 1:
Enumeration<String> parameterNames = req.getParameterNames();
while (parameterNames.hasMoreElements()) {
String key = (String) parameterNames.nextElement();
String val = req.getParameter(key);
System.out.println("A= <" + key + "> Value<" + val + ">");
}
Approach 2:
Map<String, Object> allMap = req.getParameterMap();
for (String key : allMap.keySet()) {
String[] strArr = (String[]) allMap.get(key);
for (String val : strArr) {
System.out.println("Str Array= " + val);
}
}

If you are expecting pre determined parameters then you can use getParameter(java.lang.String name) method.
Otherwise, approaches given above can be used, but with some differences, in HTTP-request someone can send one or more parameters with the same name.
For example:
name=John, name=Joe, name=Mia
Approach 1 can be used only if you expect client sends only one parameter value for a name, rest of them will be ignored. In this example you can only read "John"
Approach 2 can be used if you expect more than one values with same name. Values will be populated as an array as you showed in the code. Hence you will be able to read all values, i.e "John","Joe","Mia" in this example
Documentation

Related

Split the string of a row of datatable in asp.net

I am using asp.net. I am trying to split the data which is in datatable. I have a code sample like this:
{ dt=objErrorLoggingDataAccess.GetErrorDetails(errorID);
string[] stringSeparators = new string[] { "Message" };
string error = dt.Rows[0]["Message"].ToString();
string[] test = error.Split(stringSeparators, StringSplitOptions.None);
string PageName = test[0].ToString();
PageNameLabel.Text = PageName;
stringSeparators=new string[] {HttpContext.Current.Request.Url.ToString()};
error = dt.Rows[0]["Message"].ToString();
test = error.Split(stringSeparators, StringSplitOptions.None);
string Message = test[0].ToString();
MessageLabel.Text = Message;}
in the datatable following data is there:
{....ID.......Message.......................................................................................................................
....1........http://localhost:10489/images/CategoryIcon/images Message : File does not exist. UserName: naresh#naresh.com
....2........http://localhost:10489/images/CategoryIcon/images Message : File does not exist. UserName: iswar#iswar.com}
My problem is: how can I split the Message and store in the label? I want
{http://localhost:10489/images/CategoryIcon/images}
separately and UserName separately and the message separately. How can I do that? By executing the above code I am able to split
{ http://localhost:10489/images/CategoryIcon/images
}
only. How can I split the Message column and store in pageLabel, MessageLabel, UserNamelabel?
I would use a regular expression in this case. Because only by splitting this string looks a little bit to inflexible to me.
I tested your data example against this quick and dirty RegEx:
(?<id>\d+)\.*(?<url>\w+:\/\/[\w#][\w.:#]+\/?[\w\.?=%&=\-#/$,]*)\s*Message\s*:\s*(?<message>.*)UserName:\s*(?<username>([a-zA-Z0-9_\-\.]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3}))
It supports valid URLs and EMail patterns.
Regex regex = new Regex(
"(?<id>\\d+)\\.*(?<url>\\w+:\\/\\/[\\w#][\\w.:#]+\\/?[\\w\\.?"+
"=%&=\\-#/$,]*)\\s*Message\\s*:\\s*(?<message>.*)UserName:\\s"+
"*(?<username>([a-zA-Z0-9_\\-\\.]+)#((\\[[0-9]{1,3}\\.[0-9]{1"+
",3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|"+
"[0-9]{1,3}))",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);
// Capture the first Match, if any, in the InputText
Match m = regex.Match(InputText);
// Capture all Matches in the InputText
MatchCollection ms = regex.Matches(InputText);
// Test to see if there is a match in the InputText
bool IsMatch = regex.IsMatch(InputText);
// Get the names of all the named capture groups
// I included your fields as groups: id, url, message and username
string[] GroupNames = regex.GetGroupNames();
I don't know how often you need to call this code. Maybe you get in performance troubles if you have too much data. This regex is q&d - please adjust it to your needs.

How use a variable name to point different data types with the same name?

I have 2 List one stores the name of filterable columns(of type DropDown) and another store the values to load in those filterable columns.
List<string> filterableFields = new List<string>() { "A_B", "C_D", "E_F" };
List<string> AB, CD , EF;
Now at the run time I get the data from web service and I have written a function to to extract values for these filterable fields and store the values to 2nd List.
private void prepareListForFilterableColumns(XDocument records)
{
foreach (var currentField in filterableFields)
{
var values = (from xml in records.Descendants(z + "row")
let val = (string)xml.Attribute("ows_" + currentField.Replace("_", "_x0020_"))
where val != ""
orderby val
select val
).Distinct();
switch (currentField)
{
case "A_B": AB = values.ToList(); break;
case "C_D": CD = values.ToList(); break;
}
}
}
Now I was thinking that instead of hard coding the assignment in swtich case block, If I could just use the first List name "A_B" and replace "_" from it to point to my 2nd List and assign values.ToList() to it.
I understand that c# is a static language, So not sure if we can achieve this, but IF I can it will make my function generic.
Thanks a lot in advance for time and help.
Vishal
You could use a dictionary of lists of strings instead of 3 lists to store the values.
Dictionary<string, List<string>> val lists = new Dictionary<string,List<string>>();
And make the keys of the dictionary equal to the filterables: "AB", "CD",..
then, instead of AB you would use valLists["AB"] and could then reference reach list based on a string key.
The other option would be to use reflection but that would be slower and unnecessarily a bit more complicated.

Create a VB.NET Array with two columns of values?

I know how to create an array and loop through it normally - but what if I need a multi-column array. e.g. usually I might do something like:
For Each row in NameofArray
Dim name as String = row
Response.Write("Hello " & name & "!")
Next
But what if I want to do something like:
For Each row in NameofArray
Dim name as String = row.name
Dim age as Integer = row.age
Response.Write("Hello " & name & "! You are " & age & " years old!"
Next
If this isn't possible with an array, is there another way I can accomplish this?
Create your custom data type:
public struct DataType
public string Name;
public int Age;
}
Such type you can than use in an array like that:
DataType[] myData = new DataType[100];
myData[0].Name = "myName";
myData[0].Age = 100;
Note, if looping through that array via foreach, the elements returned for each iteration cannot get altered. If this is an requirement for you, consider using 'class' rather than 'struct' in the above DataType declaration. This will come with some other implications though. For example, the instances of a class DataType will explicitely have to be created via the 'new' keyword.
After reading your comment I think my other answer is probably what you are looking for.
What type is row and what type is NameOfArray?
If you would like to make row into a coumpound type with several members then there a several options.
Structure Row
Public Name as String
Public Age as Integer
End Structure
for instance. If you would prefer a reference type substitute Class for Structure.
Or using anonymous types,
Dim row = New With {Name = "Bob", Age = 21}
Then you can use generics to make a list of rows that you can iterate through using ForEach.
Dim NameOfList As System.Collections.Generic.List(of Row)
or if it were a result of a LINQ query somthing that supported
IEnumerable(of New With{Name As String, Age As Int}). //Not sure if this is VB
I'm not certain I uderstand your question and hope this is the kind of thing you were looking for.
As you can see from my fellow answerers, the support for anonymous types is superior in C# but, since you asked the question in VB.Net I will limit myself to that context.
After reading your comment I think I understand the question.
You can do
///Spacer Top
Dim NameOfArray = {New With {.Age = 21, .Name = "Bob"}, New With {.Age = 74, .Name = "Gramps"}}
///Spacer Bottom
If you want to create an IEnumberable anonymous type of Name Age tuples ;-p
Did you tried Dictionary Class. You can loop through the Dictionary using KeyValue pair class.
// Create a new dictionary of strings, with string keys.
//
Dictionary<string, string> openWith =
new Dictionary<string, string>();
// Add some elements to the dictionary. There are no
// duplicate keys, but some of the values are duplicates.
openWith.Add("txt", "notepad.exe");
openWith.Add("bmp", "paint.exe");
openWith.Add("dib", "paint.exe");
openWith.Add("rtf", "wordpad.exe");
foreach(var item in openWith)
{
Console.WriteLine(item.Key +" can be open with " + item.value);
}
You need to (can) index into your array using the two dimensions ie...
Dim array(,) As Object = { _
{"John",26}, _
{"Mark",4} _
}
For row As Integer = 0 to array.GetUpperBound(0)
Dim name as String = CStr(array(row,0))
Dim age as Integer = CInt(array(row,1))
Response.Write("Hello " & name & "! You are " & age & " years old!")
Next
Though would be better storing this sort of information in a class or user defined type of some kind.

How to Combine Two GUID Values

I want to combine two guid values and generate a 32 bit alphanumberic value(It can be done by using hashing).
Not Pretty, but it works..
private static Guid MungeTwoGuids(Guid guid1, Guid guid2)
{
const int BYTECOUNT = 16;
byte[] destByte = new byte[BYTECOUNT];
byte[] guid1Byte = guid1.ToByteArray();
byte[] guid2Byte = guid2.ToByteArray();
for (int i = 0; i < BYTECOUNT; i++)
{
destByte[i] = (byte) (guid1Byte[i] ^ guid2Byte[i]);
}
return new Guid(destByte);
}
and yes, I can deal with the non-unique-guarantee in my case
What about splitting the Guids into 2 chunks of 8 bytes each, convert them to ulong (8 bytes), XOR combine them and then concat the 2 results.
public static Guid Combine(this Guid x, Guid y)
{
byte[] a = x.ToByteArray();
byte[] b = y.ToByteArray();
return new Guid(BitConverter.GetBytes(BitConverter.ToUInt64(a, 0) ^ BitConverter.ToUInt64(b, 8))
.Concat(BitConverter.GetBytes(BitConverter.ToUInt64(a, 8) ^ BitConverter.ToUInt64(b, 0))).ToArray());
}
You can't convert 2 128-bit GUIDs into a 16-bit or 32-bit value and maintain uniqueness. For your stated application (use value in URL) this doesn't seem to make sense, as a given value in the URL could map to any number of GUID combinations. Have you considered this?
The best approach would be to use an URL-shortening lookup where you generate a unique ID and map it to the GUIDs if needed - similarly to bit.ly or tinyurl.com.
var a = Guid.NewGuid();
var b = Guid.NewGuid();
var hashOfXor = Xor(a, b).GetHashCode();
public static Guid Xor(Guid a, Guid b)
{
unsafe
{
Int64* ap = (Int64*) &a;
Int64* bp = (Int64*) &b;
ap[0] ^= bp[0];
ap[1] ^= bp[1];
return *(Guid*) ap;
}
}
I actually did have a need to merge two Guids together to create a third Guid.
Where the third Guid (not necessarily unique) would be the same regardless of the order the two original Guids were supplied.
So I came up with this:
public static Guid Merge(Guid guidA, Guid guidB)
{
var aba = guidA.ToByteArray();
var bba = guidB.ToByteArray();
var cba = new byte[aba.Length];
for (var ix = 0; ix < cba.Length; ix++)
{
cba[ix] = (byte)(aba[ix] ^ bba[ix]);
}
return new Guid(cba);
}
Assuming you want to generate a 32 byte value you can just concatenate the GUIDs since they are 16 byte each. If you really need a 32 bit value the only solution I see is generating your own 32 bit values and storing the related GUIDs in a database so you can retrieve them later.
In .NET Core 3 we can use Sse2/Span<T> to speed things up, and avoid all allocations. Essentially this code treats a Guid as 2 consecutive Int64 values, and performs the xor on them. SSE2 performs the xor in a single processor instruction (SIMD).
public static Guid Xor(this Guid a, Guid b)
{
if (Sse2.IsSupported)
{
var result = Sse2.Xor(Unsafe.As<Guid, Vector128<long>>(ref a), Unsafe.As<Guid, Vector128<long>>(ref b));
return Unsafe.As<Vector128<long>, Guid>(ref result);
}
var spanA = MemoryMarshal.CreateSpan(ref Unsafe.As<Guid, long>(ref a), 2);
var spanB = MemoryMarshal.CreateSpan(ref Unsafe.As<Guid, long>(ref b), 2);
spanB[0] ^= spanA[0];
spanB[1] ^= spanA[1];
return b;
}
Depends on the platform and details of what you are trying to do.
In .NET/C# you could jus take avery simple approach:
var result = g1.GetHashCode() ^ g2.GetHashCode();
I would use an UUID5 (name-based) to combine two GUIDs, see https://stackoverflow.com/a/5657517/7556646
Guid g1 = new Guid("6164742b-e171-471b-ad6f-f98a78c5557e");
Guid g2 = new Guid("acbc41aa-971c-422a-bd42-bbcefa32ffb4");
Guid g12 = Create(IsoOidNamespace, g1.ToString() + g2.ToString(), 5)
In this example g12 would be: e1ccaee5-ea5e-55c6-89a5-fac02043326e.
There's no native support in the .NET Framework for creating these, but the code is posted on GitHub that implements the algorithm.
See as well the following .NET Fiddle, https://dotnetfiddle.net/VgHLtz
Why not try a simple operator i.e. AND, OR, XOR etc. To combine the two. XOR would be your best bet hear I would imagine as it has the nice property of when xoring the result with either of the two inputs you will get the other.
Edit: having just looked at this solution, there is a problem with it. The values would have to be normalised. Take a look at Vinay's Answer for a better solution.
Here's a one-liner for you:
g1.ToByteArray().Concat(g2.ToByteArray()).GetHashCode()
public static string Merge(Guid one, Guid two)
{
return new List<Guid>() { one, two }
.OrderBy(x => x.GetHashCode())
.Select(y => y.ToString().ToLowerInvariant())
.Aggregate((a, b) => ${a.ToLowerInvariant()}_{b.ToLowerInvariant()}");
}
So in my situation i needed to maintain order in order to make sure that the 2 Guids could be merged regardless of order. Therefore they have to be ordered. That was step one. Then, it's simply selecting the guids to string and for consitency (super important), I used string.ToLowerInvariant(). Then concatenated them using the .Aggregate function.

Retrieving values of MS CRM fields through variable

I have a question about the Dynamics CRM 4.0 Webservice. I've been using it to get records from CRM into ASP.NET. After the request and the casting, the values of the columns (for instance for a contact) can be accessed through;
BusinessEntity be = getBusinessEntity(service, crmGuid, type, colnames);
contact tmp = (contact)be;
Response.Write("firstname: " + tmp.firstname + "<BR>");
Response.Write("lastname: " + tmp.lastname+ "<BR>");
I have an array of strings which identify which columns should be retrieved from CRM (colnames), for instance in this case {"firstname", "lastname"}.
But colnames can become quite big (and may not be hardcoded), so I don't want to go through them one by one. Is there a way to use something like
for(int i = 0; i < colnames.length; i++)
{
Response.write(colnames[i] + ": " + tmp.colnames[i] + "<BR>");
}
If I do this now I get an error that colnames is not a field of tmp.
Any ideas?
Not using BusinessEntity (unless you use reflection). DynamicEntity is enumerable by types deriving from Property. You'll have to do something like (I did this from memory, so might not compile)...
for(int i = 0; i < colnames.length; i++)
{
string colName = colnames[i];
foreach(Property prop in tmp)
{
if (prop.name != colName)
continue;
if (prop is StringProperty)
{
var strProp = prop as StringProperty;
Response.Write(String.Format("{0}: {1}<BR />", colName, strProp.Value));
}
else if (prop is LookupProperty)
{
...
}
... for each type deriving from Property
}
}
Reply to Note 1 (length):
Could you give me an example of what you're using. If you are only looking at the base types (Property) then you won't be able to see the value property - you'll need to convert to the appropriate type (StringProperty, etc).
In my example tmp is a DynamicEntity (it defines GetEnumerator which returns an array of Property). The other way to access the properties of a DynamicEntity is using the string indexer. For tmp:
string firstname = (string)tmp["firstname"];
Note that if you use this method, you get the Values (string, CrmNumber, Lookup) and not the whole property (StringProperty, CrmNumberProperty, etc).
Does that answer your question? Also, I recommend using the SDK assemblies and not the web references. They're much easier to use. The SDK download has a list of helper classes if you choose to use the web references, however. Search "Helper" in the SDK.

Resources