I want to send a HTTP request that looks like this:
http://api.com/main?id=1234&id=5678, the id will be GUID in string eventually.
I tried the below piece of code:
var idString = string.Join(",", listOfIds);
var queryString = new Dictionary<string, string>
{
{"id", idString}
};
requestUri = QueryHelpers.AddQueryString(requestUri, queryString);
This will give me like: http://api.com/main?id=1234,5678 but I want the style like above.
Is there anyway to achieve this without using for loop?
Thanks!
QueryHelpers doesn't work with arrays because there's no standard way to pass an array of values in a query string. Some applications accept id=1,2,3 others id=1&id=2&id=3 while others id[0]=1&id[1]=2&id[2]=3.
.NET (Core) 5 and later
AddQueryString now works with lists of KeyValuePair<string,string>or KeyValuePair<string,StringValues>
var parameters=new []{
new KeyValuePair("id",new StringValues(arrayOfIds)),
new KeyValuePair("other","value"),
...
};
var finalUri=QueryHelpers.AddQueryString(requestUri, parameters);
The StringValues constructors accept either a single string or an array of strings
Before .NET (Core) 5
String.Join itself uses a loop and a StringBuilder to create a new string without allocating temporary strings. Strings are immutable, so any string modification operation results in a new temporary string.
You could use the source code as a guide to build your own loop. A quick solution could be something like this:
string ArrayToQueryString_DONT_USE(string name,string[] values)
{
var result=new StringBuilder();
result.AppendFormat("{0}={1}",name,value);
for(int i=1;i<values.Length;i++)
{
result.AppendFormat("&{0}={1}',name,values[i]);
}
return result.ToString();
}
Unfortunately, that won't work if the parameter names or values need encoding. That's what AddQueryString does, using, once again, a StringBuilder to avoid allocating temporary strings. We can borrow that code as well:
string ArrayToQueryString(string name,string[] values)
{
var result=new StringBuilder();
result.AppendFormat("{0}={1}",name,value);
for(int i=1;i<values.Length;i++)
{
result.Append('&');
result.Append(UrlEncoder.Default.Encode(name));
result.Append('=');
result.Append(UrlEncoder.Default.Encode(values[i]));
}
return result.ToString();
}
Related
This question already has answers here:
How to parse a query string into a NameValueCollection in .NET
(19 answers)
Closed 5 years ago.
I'm trying to accept a query string of the form
?param[key1]=value1¶m[key2]=value2
and convert it into a Dictionary in C# MVC 4. This is trivial to do in PHP, but I haven't been able to find any method of reproducing this in C#.
I know I can take an array via
?param=value1¶m=value2
but that leaves issues of ordering and isn't nearly as useful for my purposes.
In the hopes that this isn't a limitation of the framework, how might I implement a dictionary-style conversion in C#?
To clarify: I'm not looking to convert a query string into an NVC, but rather to convert query string parameters into their own NVCs. This is NOT as simple as ParseQueryString() or the Request.QueryString object.
Can't you just use the Request.QueryString collection that Asp.Net provides for you? Since you are using MVC, it will be on your controllers ControllerContext property (located on that object's HttpContext property).
here I fixed some code that will work for you, defo not the best solutioin but it should work.
string basestring = "?param[key1]=value1¶m[key2]=value2";
string newstring = basestring.Replace("?", "").Replace("param[", "").Replace("]", "");
var array = newstring.Split('&');
var dictionary = new Dictionary<string, string>();
foreach (var onestring in array)
{
var splitedstr = onestring.Split('=');
dictionary.Add(splitedstr[0],splitedstr[1]);
}
You can also try something like this
public ActionResult SubmitFormWithFormCollection(FormCollection parameters)
{
foreach (string param in parameters)
{
ViewData[param] = parameters[param];
}
return View();
}
I have a list of String defined like this
List<String> lstHeaders = new List<string>(new String[]{"str","str1","str2"});
I a want a way to join all that elemenet with an specific format to get something like this
<td>str</td><td>str1</td><td>str2</td>
but get this just in online of code , something like this
"<th>"+lstHeaders.functionToGetFormated()+"</th>"
Use the StringBuilder class:
var sb = new StringBuilder();
lstHeaders.ForEach(x => sb.AppendFormat("<td>{0}</td>", x));
return sb.toString()
Probably makes more sense to write your own extension method for this. Nothing built-in will work exactly like that (that I am aware of).
public static string WrapElementsWithTag(this IEnumerable<string> input, string wrapper)
{
StringBuilder sb = new StringBuilder();
foreach (string s in input)
{
sb.AppendFormat("<{1}>{0}</{1}>", s, wrapper);
}
return sb.ToString();
}
Called like;
lstHeaders.WrapElementsWithTag("td");
Using Linq and String.Concat:
string result = string.Concat(lstHeaders.Select(s => string.Format("<td>{0}</td>", s)));
Perhaps clearer with query syntax:
string result = string.Concat(from s in lstHeaders select string.Format("<td>{0}</td>", s));
You could do something like:
string.Format("<td>{0}</td>", string.Join("</td><td>", lstHeaders));
Generally simple string concatenation is risky against constructing meta data like html and xml. If you are absolute sure that the text wont corrupt the meta syntax, you may surely do it with with StringBuilder or LinQ. Say, those strings were already escaped.
Otherwise, you may consider using HtmlTextWriter. And it shouldn't be hard to use HtmlTextWriter in LINQ.
I have a dictionary object which i would like to encrypt, then put it in a querystring, then decrypt it on the other side.
I'm using JavaScriptSerializer for this. Now i've tried this on the same page onload, and it worked. So the encrypt/decrypt extension methods im using are working. This leads me to believe there's some issue going on with the querystring.
e.g.
var js = new JavaScriptSerializer();
var d = new Dictionary<string, string>();
d.Add("ID", "123456");
d.Add("Name", "HELLO TEST");
d.Add("Email", "test#email.com");
var s = js.Serialize(d).EncryptString();
var ds = js.Deserialize<Dictionary<string, string>>(s.DecryptString());
#ViewBag.Test = ds["Name"];
In the above example, EncryptString() and DecryptString() are the extension methods i'm using. This works as intended, so it pulls the correct value for "Name".
I run into problems when I put the serialized encrypted string into the querystring then try and decode it.
So on the first page, i have something like this:
var js = new JavaScriptSerializer();
var d = new Dictionary<string, string>();
d.Add("ID", "123456");
d.Add("Name", "HELLO TEST");
d.Add("Email", "test#email.com");
var s = HttpUtility.UrlEncode(js.Serialize(d).EncryptString());
s is then used as the querystring.
On the receiving page, i have this:
public ActionResult Display(string r)
{
var js = new JavaScriptSerializer();
var decryptedString = HttpUtility.UrlDecode(r).DecryptString();
var s = js.Deserialize<Dictionary<string, string>>(decryptedString);
return View();
}
This throws an error: System.FormatException: Invalid length for a Base-64 char array or string. This errors on the decryptstring line.
I don't get what's going on... I'm urlencoding the text before it goes into the querystring, then urldecoding it before it's deserialized..
EDIT
Figured it out.. I was encrypting it twice...
Chances are that you don't need to UrlDecode your string, because MVC will have done that before assigning the value of your r parameter. Try decrypting r directly.
And of course, I have to issue the warning: what you're doing here seems like a very bad idea. Whatever you're trying to accomplish by sending this encrypted dictionary in the URL, there is almost certainly a better way to accomplish it.
Most likely some characters don't roundtrip the way you expect (i.e. "+" tends to become space in this case).
Check with Fiddler (or any other HTTP debugging tool) what is actually send to/from your server. Than check if string that comes to you "Display" action - cood chance that you see what is wrong.
I have a lot of functions that look like this. Each has N arguments and each creates an SQLparamater array with each paramater being of this very similar form.
[WebMethod]
public static string accessServer(string dataField1, string dataField2, string dataField3) {
string value;
SQLParamater[] param = new SQLParameter[len] // len is the amount of arguments
param[0] = new SQLParameter("#dataField1", dataField1);
param[1] = new SQLParameter("#dataField2", dataField2);
param[2] = new SQLParameter("#dataField3", dataField3);
...
// do something with param
return value;
}
This looks like it can be done generically using a combination of Reflection and accessing the paramaters in a generic way.
Ideally a method of the form
public static SQLParamater[] getParams(someType paramaters)
and SQLParamater[] param = getParams(...)
I'm not sure how to pass on all the paramaters generically.
[Edit]
Note that the names of these datafields are important. It's not just an array of strings but rather a set of key/value pairs.
[/Edit]
You can use a function with variable arguments: name(params string[] arguments), so you can call, for example: name(arg1,arg2,arg3,arg4);
This has been asked about before (can't find that question though), the problem however is that while you can figure out the parameter names by using reflection MethodBase.GetCurrentMethod() you can't zip those names together with the parameter values because there's no way for you to access a parameter list of values.
There are other ways of trying to work around this very specific tiresome problem but I don't recommend doing it this way, it just doesn't make a lot of sense.
Now, given a method like this:
static void SomeMethod(string arg1, int arg2, object arg3)
{
}
You could do this:
static void Main()
{
var b = 123;
// this now becomes necessary as it's the only way of getting at the metadata
// in a presumable safe manner
Expression<Action> x = () => SomeMethod("a", b, "a" + b);
var args = GetArgs(x);
foreach (var item in args)
{
Console.WriteLine("{0}: {1}", item.Key, item.Value);
}
}
And implement the GetArgs method like so (you still need a way of putting those values somewhere becuase the invocation never occurs):
static IDictionary<string, object> GetArgs(Expression<Action> x)
{
var args = new Dictionary<string, object>();
var m = (MethodCallExpression)x.Body;
var parameters = m.Method.GetParameters();
for (int i = 0; i < m.Arguments.Count; i++)
{
// an easy way of getting at the value,
// no matter the complexity of the expression
args[parameters[i].Name] = Expression
.Lambda(m.Arguments[i])
.Compile()
.DynamicInvoke();
}
return args;
}
You infer the collection of name/value pairs from the expression tree created by the compiler, it's doable but kind of odd.
I think your API design is flawed if you need this, you would better have one method, which accepts a collection of some sort.
Code duplication like this is almost never the correct way to get things done.
EDIT
On topic:
I guess you can get the values from the stack: http://www.thescarms.com/dotnet/StackFrame.aspx
we do it like this:
var dict=new Dictionary
{
{"#param1",value1},
{"#param2",value2},
{"#param3",value3},
{"#param4",value4},
....
};
DALayer.ExecuteProc("procName",dict);
In the ExecuteProc function you can iterate over Dictionary object and set params using KeyValuePair object. But if you have to setup the datatype, lengths etc for the parameters then you have to do more work like preparing the sql command to query about parameters or passing more complicated object as parameter that contains information about datatype, length and direction etc.
I'm trying to call a C# method from JavaScript by using ActiveXObject:
var myobj = new ActiveXObject('myobject');
var arr = myobj.GetArray();
Eventually, arr will contain a SAFEARRAY object, but not JScript array. Is there any way to return native JavaScript object from a C# method?
You can return a JSON string and then parse into a JavaScript object. There are a number of .NET libraries available to serialize .NET objects into JSON and vice-versa-
JSON.NET
Microsoft ASP.NET AJAX library
JSONSharp
to name a few.
This question and answer may be of use to you
I found the solution by myself, but no documentation exists for this part.
The solution is to use JScript.ArrayObject in the following way:
ArrayObject _lastField;
byte[] byteArray = new byte[]{2,1,2,3};
object[] array = new object[byteArray.Length];
byteArray.CopyTo(array, 0);
_lastField = Microsoft.JScript.GlobalObject.Array.ConstructArray(array);
After that you will be able to use the _lastField array in JavaScript like a native array:
var myobj = new ActiveXObject('myobject');
var arr = myobj.LastField;
alert(arr[1]);
You may return delimited Joined String in C# and can split into JavaScript
//C#
public string getArryString()
{
string[] arrstring = new string[]{"1","2","3"};
return string.Join(",", arrstring);
}
//Javascript
var arrstring = objActiveX.getArryString().split(',');
Via VBArray it can work like this:
Return object[] from C# (declare so in the dispinterface).
To get a native JS array in JScript use VBArray:
var jsArray = new VBArray(myobj.GetArray()).toArray();
for (i = 0; i < jsArray.length; i++)
{
// use jsArray[i]
}
Background information:
JScript supports SafeArrays of Variants only
http://blogs.msdn.com/b/jaiprakash/archive/2007/01/09/jscript-supports-safearrays-of-variants-only.aspx
Eric's Complete Guide To Type Signatures Of Scriptable Object Models
http://blogs.msdn.com/b/ericlippert/archive/2004/07/14/183241.aspx