How to ignore if var is null c# - 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

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.

Twitter API Authorisation problem - 401 Error

I'm having trouble getting a call to the Twitter API working.
I'm having to do this as the package i was using has got an issue and the fix isn't compatible with my project.
I want to retrieve a list of 'recent' tweets but I keep getting a 401. I have a feeling it is because of the way I'm creating my signature but I'm not certain.
My request URL is:
https://api.twitter.com/1.1/search/tweets.json?result_type=recent&count=1&q=#hashtag1 OR #hashtag2 OR #hashtag3
I have the following auth info:
Dictionary<string, object> _parameters = new Dictionary<string, object>();
_parameters.Add("oauth_version", "1.0");
_parameters.Add("oauth_nonce", "[VALUE]");
_parameters.Add("oauth_timestamp", [TIMESTAMP]);
_parameters.Add("oauth_signature_method", "HMAC-SHA1");
_parameters.Add("oauth_consumer_key", "[VALUE]");
_parameters.Add("oauth_consumer_secret", "[VALUE]");
_parameters.Add("oauth_token", "[VALUE]");
_parameters.Add("oauth_token_secret", "[VALUE]");
My 'create signature' method is as follows. It uses the full URL with search parameters to construct it:
private static string GenerateSignature(Dictionary<string,object> parameters, Uri requestUri, string consumerSecret, string accessTokenSecret)
{
IEnumerable<KeyValuePair<string, object>> nonSecretParameters;
nonSecretParameters = (from p in parameters
where (!SecretParameters.Contains(p.Key))
select p);
Uri urlForSigning = requestUri;
string signatureBaseString = string.Format(
CultureInfo.InvariantCulture,
"{0}&{1}&{2}",
"GET",
UrlEncode(NormalizeUrl(urlForSigning)),
UrlEncode(nonSecretParameters));
string key = string.Format(
CultureInfo.InvariantCulture,
"{0}&{1}",
UrlEncode(consumerSecret),
UrlEncode(accessTokenSecret));
HMACSHA1 hmacsha1 = new HMACSHA1(Encoding.UTF8.GetBytes(key));
byte[] signatureBytes = hmacsha1.ComputeHash(Encoding.UTF8.GetBytes(signatureBaseString));
return Convert.ToBase64String(signatureBytes);
}
private static string UrlEncode(string value)
{
if (string.IsNullOrEmpty(value))
{
return string.Empty;
}
value = Uri.EscapeDataString(value);
value = Regex.Replace(value, "(%[0-9a-f][0-9a-f])", c => c.Value.ToUpper());
value = value
.Replace("(", "%28")
.Replace(")", "%29")
.Replace("$", "%24")
.Replace("!", "%21")
.Replace("*", "%2A")
.Replace("'", "%27");
value = value.Replace("%7E", "~");
return value;
}
private static string NormalizeUrl(Uri url)
{
string normalizedUrl = string.Format(CultureInfo.InvariantCulture, "{0}://{1}", url.Scheme, url.Host);
if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443)))
{
normalizedUrl += ":" + url.Port;
}
normalizedUrl += url.PathAndQuery + url.Fragment.Replace("%20", " ");
return normalizedUrl;
}
Once I have the signature, I generate my Authorisation header which is something like this:
OAuth oauth_consumer_key="[VALUE]",oauth_nonce="[VALUE]",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1565261231",oauth_token="[VALUE]",oauth_version="1.0",oauth_signature="[VALUE]"
Then I append the relevant auth params to the URL and make the request to the Twitter API. The final URL is something like this:
https://api.twitter.com/1.1/search/tweets.json?result_type=recent&count=1&q=%23hashtag1 OR %23hashtag2 OR %23hashtag3

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);

Append key value pairs to query string

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);

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.

Categories