Append key value pairs to query string - c#

I want to add multiple query string key value pairs to an url by formatting a regular string and then appending this to the current query string. Because, in my knowledge, there is no way to change the actual Request.QueryString. Therefore I try to append the kvp:s to the query string as per below. I have searched StackOverflow, but I couldn't find an answer that matches my problem.
protected void ServiceSelectionChanged(object sender, EventArgs e)
{
var regNr = registrationNumber.Text;
var selectedServiceType = SelectedServiceType.ToString("D");
string url = string.Empty;
BookingHelpers.FormatQueryStringUrl(this.Request, "serviceType", selectedServiceType, ref url);
BookingHelpers.FormatQueryStringUrl(this.Request, "regNr", regNr, ref url);
Server.Transfer(url, false);
}
public static void FormatQueryStringUrl(HttpRequest request, string key, string value, ref string url)
{
if (string.IsNullOrEmpty(url))
{
url = request.Url.PathAndQuery;
}
if (url.Contains("?"))
{
if (url.Contains("&" + key))
{
string currentValue = request.QueryString[key];
url = url.Replace("&" + key + "=" + currentValue, "&" + key + "=" + value);
}
else
{
url = String.Format(request.Url.PathAndQuery + "&" + key + "={0}", value);
}
}
else url = String.Format(request.Url.PathAndQuery + "?" + key + "={0}", value);
}
This however uses the Request.QueryString each time, so the first kvp is overwritten. So my question is: How can I make this work so that i can append both of the key value pairs to the query string?

I found an answer on stack overflow that helped me:
How to build a query string for a URL in C#?
Although, I also needed to check if the url already had a query string in it, so i modified it to something like this.
public static string ToQueryString(string url, NameValueCollection nvc)
{
StringBuilder sb;
if (url.Contains("?"))
sb = new StringBuilder("&");
else
sb = new StringBuilder("?");
bool first = true;
foreach (string key in nvc.AllKeys)
{
foreach (string value in nvc.GetValues(key))
{
if (!first)
{
sb.Append("&");
}
sb.AppendFormat("{0}={1}", Uri.EscapeDataString(key), Uri.EscapeDataString(value));
first = false;
}
}
return url + sb.ToString();
}
And the usage instead became:
var queryParams = new NameValueCollection()
{
{ "isaServiceType", selectedIsaServiceType },
{ "regNr", regNr }
};
var url = ToQueryString(Request.Url.PathAndQuery, queryParams);

Related

How to create hash in C# like in PHP example?

I have to rewrite this php code to c#
$sign_params = ['name'=>"John", 'age'=>18];
$client_secret = 'test secret key';
ksort($sign_params); // Sort array by keys
$sign_params_query = http_build_query($sign_params); // Forming string like "param_name1=value&param_name2=value"
$sign = rtrim(strtr(base64_encode(hash_hmac('sha256', $sign_params_query, $client_secret, true)), '+/', '-_'), '='); // get hash code
return $sign;
Here what I try:
public class apiHelper : MonoBehaviour
{
const string client_secret = "test secret key";
public static string checkSign(Dictionary<string, dynamic> fields)
{
//* sort by keys
var list = fields.Keys.ToList();
list.Sort();
string sign_params_query = "";
//* forming string like "param_name1=value&param_name2=value"
foreach (var key in list)
{
sign_params_query = sign_params_query + key + "=" + fields[key];
if (key != list.Last()) sign_params_query = sign_params_query + "&";
}
//* get hash code
string sign = System.Convert.ToBase64String(GetHash(sign_params_query, client_secret));
char[] charsToTrim = { '=' };
return sign.Replace("+", "-").TrimEnd(charsToTrim);
}
static byte[] GetHash(string url, string key)
{
using (HMACSHA256 hmac = new HMACSHA256(Encoding.ASCII.GetBytes(key)))
{
byte[] data = hmac.ComputeHash(Encoding.UTF8.GetBytes(url));
return data;
}
}
}
Well, finally I get different hash than in php example ._. What did I wrong? Its my 1st time with cryptho or smth like that
Well, problem wath with strings which have special chars. I have to use url_encode c# equivalent to solve it.

how to pass a variable number of parameters inside a url

hello I am trying to pass a variable number of parameters inside a HttpWebRequest url. My approach so far is this-
public static async Task<ObservableCollection<Anime>> RequestsAnime(string accessToken, int page = 0, params string[] optionals) // All Anime
{
JsonWebClient client = new JsonWebClient();
string baseUri = "https://anilist.co/api/browse/anime?access_token=" + accessToken;
string completeUri = "";
string parameters = "";
if (optionals != null)
{
parameters = CollectionUtils.ToStringFromArray(optionals);
completeUri = baseUri + parameters;
}
if (page != 0)
{
completeUri = baseUri + "&page=" + page;
}
HttpWebRequest reqForToken = HttpWebRequest.CreateHttp(completeUri);
reqForToken.Method = "GET";
var respToken = await client.DoRequestJsonAsync<ObservableCollection<Anime>>(reqForToken);
return respToken;
}
ToStringFromArray function
public static string ToStringFromArray(string[] arrayString)
{
string result = string.Join("", arrayString);
return result;
}
RequestsAnime Calling
string[] ds = new string[] { "&status", "=active", "&season","=fall" };
var nm = await Requests.CreateMultipleTasksAsync(ds);
CreateMultipleTaskAsync calling
public static async Task<ObservableCollection<Anime>> CreateMultipleTasksAsync(int page=0 ,params string[] optionals)
{
Task<Auth> download1 = RequestsAuth();
Auth length1 = await download1;
Task<ObservableCollection<Anime>> download2 = RequestsAnime(download1.Result.Access_token,page, optionals);
var animeList = await download2;
return animeList;
}
I know its a clumsy way. I need to know a better solution. My objectives are-
Pass variable amount of parameters inside the URL
Append the parameters with "&" and "="
I would suggest you put all your query string parameters in a Dictionary:
var parameters = new Dictionary<string, string>
{
{ "status", "active" },
{ "season", "fall" }
};
You can then call the following method generate a valid query string (notice the calls to Uri.EscapeDataString:
string CreateQueryString(Dictionary<string, string> parameters)
{
return String.Join("&", parameters
.Select(param => String.Format("{0}={1}",
Uri.EscapeDataString(param.Key),
Uri.EscapeDataString(param.Value)))
.ToArray());
}
Just append the queryString to you baseUri:
completeUri = baseUri + "&" + CreateQueryString(parameters);

How to ignore if var is null c#

I'm joining a load of strings to make a superstring but i need to ignore a param if one is null. Currently i cannot think how to do this other than emcompassing all the params in seperate if statements. Help pls:
Here the code
public void LinkBuilder(string baselink, string sharedkey, string service, string period, string bulletintype,
string includeresults, string includemap, string username, string password)
{
sharedkey = "&" + sharedkey;
service = "&" + service;
period = "&" + period;
bulletintype = "&" + bulletintype;
includeresults = "&" + includeresults;
includemap = "&" + includemap;
username= "&" + username;
password = "&" + password;
string completeLink = sharedkey + service + period + bulletintype + includeresults + includemap + username +
password;
Not sure how to tackle this.
I would really refactor it this way:
public void LinkBuilder(params string[] links)
{
string completeLink = String.Join("&", links.Where(x=>!String.IsNullOrEmpty(x)));
}
If the objective is to avoid wrapping each parameter in an if statement, you could add them to a list, then use String.Join, and Linq.Select
public void LinkBuilder(string baselink, string sharedkey, string service, string period, string bulletintype,
string includeresults, string includemap, string username, string password)
{
var allParams = new List<string>
{
baselink,
sharedkey,
service,
period,
bulletintype,
includeresults,
includemap,
username,
password
};
var completeLink = "?" + String.Join("&", allParams.Select(p => p != null));
}
You can do a check of strings by operator ?: in method.
public void LinkBuilder(string baselink, string sharedkey, string service, string period, string bulletintype,
string includeresults, string includemap, string username, string password)
{
sharedkey = checkValue(sharedkey);
service = checkValue(service );
period = checkValue(period );
bulletintype = checkValue(bulletintype );
includeresults = checkValue(includeresults );
includemap = checkValue(includemap );
username= checkValue(username );
password = checkValue(password );
string completeLink = sharedkey + service + period + bulletintype + includeresults + includemap + username +
password;
}
private String checkValue(String str)
{
return str != null ? "&" + str : "";
}
Below would accept a Collection which I feel may be better maintainable. I re factored a bit.
public string LinkBuilder(Dictionary<string, string> parameters)
{
var url = String.Empty;
foreach(var parameter in parameters)
if(!string.IsNullOrEmpty(parameter.Value))
url += String.Format("&{0}={1}", parameter.Key, parameter.Value);
return url;
}
This way you would pass a collection to build your URL, then it would return the giant URL for you. You have a massive selection, I personally like Maksim's answer.
Make an enumerable collection of your strings, use a bit of linq to filter out the nulls, then join it all back together again with String.Join:
var elements =
new[]{baselink, sharedkey, service, period,
bulletintype, includeresults, includemap,
username, password};
var nonNullElements = elements.Where(e => e != null);
var outputString = String.Join("&", nonNullElements);
On the off-chance that you're actually trying to assemble a querystring, there are better ways.
For instance, you could leverage HttpUtility and reflection using the following method for parsing an anonymous object to a query string:
public static class ObjEx
{
public static string ToQueryString(this object data)
{
var collection = data.GetType()
.GetProperties()
.Aggregate(
HttpUtility.ParseQueryString(string.Empty),
(prev,curr) => {
var val = curr.GetValue(data);
var propName = curr.Name;
prev.Add(propName,val.ToString());
return prev;
});
return collection.ToString();
}
}
then
var data = new{foo = "bar", num = 1, cat = "bad", dog = "good", needsEscaping = "é\"&"};
Console.WriteLine(data.ToQueryString());
will give you:
foo=bar&num=1&cat=bad&dog=good&needsEscaping=%u00e9%22%26

Validate Google Account using WebClient

I am trying validate Google Account using WebClient.
class PostDataBuilder
{
private static Dictionary<string, string>
ToPropertyDictionary(object data)
{
var values = data
.GetType()
.GetProperties()
.Select(x => new {
Key = x.Name,
Value = x.GetValue(data, null)
});
var result = new Dictionary<string, string>();
foreach (var item in values)
result.Add(item.Key, item.Value.ToString());
return result;
}
public static string Build(object data)
{
string result = "";
var dict = ToPropertyDictionary(data);
foreach (var name in dict.Keys)
result += name + "=" + HttpUtility.UrlEncode(dict[name]) + "&";
return result.Substring(0, result.Length - 1);
}
}
class Program
{
static void Main(string[] args)
{
string postText = PostDataBuilder.Build(
new
{
dsh = "-1903339439726094408",
GALX = "-Ggrv6gqusk",
timeStmp = "",
secTok = "",
Email = "WrongEmail#gmail.com",
Passwd = "WrongPassword",
signIn = "?????",
rmShown = "1"
});
byte[] data = Encoding.UTF8.GetBytes(postText);
WebClient wc = new WebClient();
byte[] result = wc.UploadData(
new Uri("https://accounts.google.com/ServiceLoginAuth"),
"POST", data);
string resultText = Encoding.UTF8.GetString(result);
}
}
ResultText variable has setted , even if data is correct. What's wrong?
You shouldn't ever screw around with login services such as the Google one or try to fake a browser. In the end it could be considered attempt hacking or whatever and it's very likely to break the next time they update their page (or even just because your IP changes).
Instead use OpenID or OAuth as described here.

Remove a value from querystring in MVC3 and redirect to the resulting URL

I'm working on a seemingly simple issue: in my Authorization filter I'm checking for a few things if one of the conditions is not met, I need to remove certain values from the Query string and redirect the user to the resulting URL. However, this is giving me a few more problems than I would like. It looks something like this:
public void OnAuthorization(AuthorizationContext filterContext)
{
if (!SomeCondition()) {
RedirectToCleanUrl(filterContext);
}
}
In my RedirectToCleanUrl I'm stripping the query strings and attempt to redirect them to the new url. It looks like this:
private void RedirectToCleanUrl(AuthorizationContext filterContext)
{
var queryStringParams = new NameValueCollection(filterContext.HttpContext.Request.QueryString);
// Stripping the key
queryStringParams.Remove("some_key");
var routeValueDictionary = new RouteValueDictionary();
foreach (string x in queryStringParams)
{
routeValueDictionary.Add(x, queryStringParams[x]);
}
foreach (var x in filterContext.RouteData.Values)
{
routeValueDictionary.Add(x.Key, x.Value);
}
filterContext.Result = new RedirectToRouteResult(routeValueDictionary);
}
First off all, it doesn't work and even if it did, it's ugly. There must be a better way, right? What am I missing here?
Here's the code I ended up writing:
protected void StripQueryStringAndRedirect(System.Web.HttpContextBase httpContext, string[] keysToRemove)
{
var queryString = new NameValueCollection(httpContext.Request.QueryString);
foreach (var key in keysToRemove)
{
queryString.Remove(key);
}
var newQueryString = "";
for (var i = 0; i < queryString.Count; i++)
{
if (i > 0) newQueryString += "&";
newQueryString += queryString.GetKey(i) + "=" + queryString[i];
}
var newPath = httpContext.Request.Path + (!String.IsNullOrEmpty(newQueryString) ? "?" + newQueryString : String.Empty);
if (httpContext.Request.Url.PathAndQuery != newPath)
{
httpContext.Response.Redirect(newPath, true);
}
}
You might also want to UrlEncode the query string params, but I'll leave this up to you.

Categories