I am trying to do some group comparison in my web application and want to see if the current user is in a certain list of groups that I have stored in a SQL table. I currently am getting my groups in an array using this method...
public ArrayList GetGroups()
{
ArrayList groups = new ArrayList();
foreach (System.Security.Principal.IdentityReference group in
System.Web.HttpContext.Current.Request.LogonUserIdentity.Groups)
{
groups.Add(group.Translate(typeof
(System.Security.Principal.NTAccount)).ToString());
}
return groups;
}
From here I can check if the user is in a certain group by doing this
ArrayList al = new ArrayList();
al = GetGroups();
foreach (string s in al)
{
if (s == "some_group")
{
//do this;
}
}
I can get it working for individual or even a few groups but I have a SQL table with about 20 groups in it and I just wanted to use some sort of comparison between the array and my SQL table. I tried using a dataset and comparing them but I was not able to get that working. Any advice is appreciated I am just learning how to work in C#. Thank you.
Few things I noticed from your code:
There is no reason to use ArrayList. Instead use a List<T> where in your case, T would be string. This provides type safety and better performance.
You create a new instance of the ArrayList class and then you assign the result of GetGroups to that variable (al). You initialized an instance of the ArrayList for no purpose, you already created the instance in the GetGroups method.
I'm not quite sure what comparison you are wanting to do between the user groups and the SQL groups. Feel free to add more details, but you can do a very basic contains check like so:
List<string> userGroups = GetUserGroups();
List<string> sqlGroups = GetSqlGroups();
foreach (var sqlGroup in sqlGroups)
{
// case-sensitive check
if (userGroups.Contains(sqlGroup))
{
// the user has one of the SQL groups
}
// case-insensitive check
if (userGroups.Contains(sqlGroup, StringComparer.OrdinalIgnoreCase))
{
// the user has one of the SQL groups
}
}
You can get more advanced using LINQ or even if you need to consider cAsE sEnsiTiviTY, but you'll need to provide more details for that.
List<string> userGroups = new List<string>();
List<string> sqlGroups = new List<string>();
var containedGroups = sqlGroups.Where(item=>userGroups.Contains(item));
Generic List is better than ArrayList if you can make sure your data type.
Related
I think the answer to this is pretty obvious, but it's friday so my brain isn't functioning entirely.
I'm working in an asp.net mvc application where I get the id of a selected row. Every time I click a row the id of that row is send to my controller.
What I want to do is output the id just as regular plain text.
This isn't too hard, I use this code:
public string GetInformation(int id)
{
return id.toString();
}
But the user can select multiple rows at once, what happens now is that the id just changes from the first selected row to the second one.
What I want is both the id's to be returned, separated by a comma.
This is what I tried:
public string[] GetInformation(int id)
{
List<string> oud = new List<string>();
oud.Add(id.ToString());
return oud.ToArray();
}
But then it just shows System.String[] as output.
Ok, I'm going to prefix this by saying that I think using sessions for state is generally a bad idea. However, it's an easy way to show state management and retaining the list between requests.
Update your function to this:
public string[] GetInformation(int id)
{
var list = Session["oud"] as List<string>;
if (list == null)
{
list = new List<string>();
Session["oud"] = list;
}
list.Add(id.ToString());
return list.ToArray();
}
Each time you call this method it will get the list from session (user state management). If the list returned from session is null (it's not actually there) we create a new list of strings and add it to the session.
To test this I put the following in an index action of an MVC controller before return View(). When I refresh the page I can see the random id being appended to the list. The same will apply if you make a call from the client.
Random r = new Random();
GetInformation(r.Next(1, 10));
Hope this helps!
Update
Iterating over an array in razor view and printing each item
In your razor view, if you have added this array to your model as MyIds, you could use the following:
#foreach (var id in Model.MyIds)
{
<p>#Html.Raw(id)</p>
}
Update 2
I'm going to make this very easy for you:
public string GetInformation(int id)
{
var list = Session["oud"] as List<string>;
if (list == null)
{
list = new List<string>();
Session["oud"] = list;
}
list.Add(id.ToString());
return string.Join(", ", list);
}
The function now returns a comma separated list of ids that you have passed through.
But then it just shows System.String[] as output.
Well, you're not showing us how you actually output anything. But presumably you're getting a value:
var output = GetInformation(input);
and then trying to write output directly as a string. However, string[] is an array and doesn't have a default string representation. All objects in .NET which don't have a .ToString() implementation inherit their implementation from System.Object, which defaults to outputting the type name.
Instead of outputting the object itself, which is semantically something like this:
Write(output)
(again, semantically, since we don't know how you're actually outputting it, so consider this pseudo-code)
Loop over it for your output:
foreach (var value in output)
Write(value)
You'll have to handle formatting (new lines, delimiters, etc.) for however you want to display the values as a UI concern. But the point, basically, is that you need to loop over your values and output them individually rather than as one big array.
There are shortcuts which will loop over it for you, if you'd like. For example:
Write(string.Join(",", output))
That would "join" all of the strings in output for you, using "," as a delimiter.
Edit: Another problem that you seem to be experiencing is that your method only ever returns a new list of exactly one object:
public string[] GetInformation(int id)
{
List<string> oud = new List<string>();
oud.Add(id.ToString());
return oud.ToArray();
}
This method shouldn't really have the responsibility of maintaining the list. This is because the method itself is stateless, all it really does is convert an integer value to a string. (Which you don't really need a method for, but whatever.) Consuming code should maintain state.
So keep the method as-is:
public string GetInformation(int id)
{
return id.toString();
}
And have the consuming code maintain the collection of values. Something like this:
var output = GetInformation(input);
myOutputs.Add(output);
Where is myOutputs defined? Well, where that state is maintained depends on a lot of things. This is a web application, so state can be an interesting thing. There are many places to maintain it:
Within the consuming method as a method-level variable
Within the consuming class as a class-level value
In session state
In a database
etc.
The overall flow of the logic and the application is going to govern this. For example, if a single instance of the class is maintaining the entire lifetime of this process then you would put it in a class-level value. However, if the value needs to persist across different page requests then you might want to put it in Session State instead. You have a number of options for where to maintain this collection of strings.
Try this:
PSEUDO CODE
public string[] GetInformation(int id)
{
List<string> oud = new List<string>();
oud.Add(id.ToString());
return oud.ToArray();
}
var myResult = GetInformation(1);
Console.WriteLine(string.Join(", ", myResult);
It's more nice to return unformatted data and format it when needed.
public int[] GetInformation(int id)
{
List<int> oud = new List<int>();
oud.Add(id);
return oud.ToArray();
}
var myResult = GetInformation(1);
Console.WriteLine(string.Join(", ", myResult);
I'm using a view returning Domains according to an id. The Domains column can be 'Geography' or can be stuffed domains 'Geography,History'. (In any way, the data returned is a VARCHAR)
In my C# code, I have a list containing main domains:
private static List<string> _mainDomains = new List<string>()
{
"Geography",
"Mathematics",
"English"
};
I want to filter my LINQ query in order to return only data related to one or many main Domain:
expression = i => _mainDomains.Any(s => i.Domains.Contains(s));
var results = (from v_lq in context.my_view
select v_lq).Where(expression)
The problem is I can't use the Any key word, nor the Exists keyword, since they aren't available in SQL. I've seen many solutions using the Contains keyword, but it doesn't fit to my problem.
What should I do?
You can use contains:
where i.Domains.Any(s => _mainDomains.Contains<string>(s.xxx))
Notice that the generic arguments are required (even if Resharper might tell you they are not). They are required to select Enumerable.Contains, not List.Contains. The latter one is not translatable (which I consider an error in the L2S product design).
(I might not have gotten the query exactly right for your data model. Please just adapt it to your needs).
I figured it out. Since I can't use the Any keyword, I used this function:
public static bool ContainsAny(this string databaseString, List<string> stringList)
{
if (databaseString == null)
{
return false;
}
foreach (string s in stringList)
{
if (databaseString.Contains(s))
{
return true;
}
}
return false;
}
So then I can use this expression in my Where clause:
expression = i => i.Domains.ContainsAny(_mainDomains);
Update:
According to usr, the query would return all the values and execute the where clause server side. A better solution would be to use a different approach (and not use stuffed/comma-separated values)
Sorry, I think I was not clear earlier. I am trying to do as O.R.mapper says below- create a list of arbitrary variables and then get their values later in foreach loop.
Moreover, all variables are of string type so I think can come in one list. Thanks.
Is there a way to store variables in a list or array then then loop through them later.
For example: I have three variables in a class c named x,y and Z.
can I do something like:
public List Max_One = new List {c.x,c.y,c.z}
and then later in the code
foreach (string var in Max_One)
{
if ((var < 0) | (var > 1 ))
{
// some code here
}
}
Is there a particular reason why you want to store the list of variables beforehand? If it is sufficient to reuse such a list whenever you need it, I would opt for creating a property that returns an IEnumerable<string>:
public IEnumerable<string> Max_One {
get {
yield return c.x;
yield return c.y;
yield return c.z;
}
}
The values returned in this enumerable would be retrieved only when the property getter is invoked. Hence, the resulting enumerable would always contain the current values of c.x, c.y and c.z.
You can then iterate over these values with a foreach loop as alluded to by yourself in your question.
This might not be practical if you need to gradually assemble the list of variables; in that case, you might have to work with reflection. If this is really required, please let me know; I can provide an example for that, but it will become more verbose and complex.
Yes, e.g. if they are all strings:
public List<string> Max_One = new List<string> {c.x,c.y,c.z};
This uses the collection initializer syntax.
It doesn't make sense to compare a string to an int, though. This is a valid example:
foreach (string var in Max_One)
{
if (string.IsNullOrEmpty(var))
{
// some code here
}
}
If your properties are numbers (int, for example) you can do this:
List<int> Max_One = new List<int> { c.x, c.y, c.Z };
and use your foreach like this
foreach(int myNum in Max_One) { ... } //you can't name an iterator 'var', it's a reserved word
Replace int in list declaration with the correct numeric type (double, decimal, etc.)
You could try using:
List<object> list = new List<object>
{
c.x,
c.y,
c.z
};
I will answer your question in reverse way
To start with , you cannot name your variable with "var" since it is reserved name. So what you can do for the foreach is
foreach (var x in Max_One)
{
if ((x< 0) || (x> 1 ))
{
// some code here
}
}
if you have .Net 3.0 and later framework, you can use "var" to define x as a member of Max_One list without worrying about the actual type of x. if you have older than the version 3.0 then you need to specify the datatype of x, and in this case your code is valid (still risky though)
The last point (which is the your first point)
public List Max_One = new List {c.x,c.y,c.z}
There are main thing you need to know , that is in order to store in a list , the members must be from the same datatype, so unless a , b , and c are from the same datatype you cannot store them in the same list EXCEPT if you defined the list to store elements of datatype "object".
If you used the "Object" method, you need to cast the elements into the original type such as:
var x = (int) Max_One[0];
You can read more about lists and other alternatives from this website
http://www.dotnetperls.com/collections
P.s. if this is a homework, then you should read more and learn more from video tutorials and books ;)
I'm trying to make a function with list.
It is to sort and delete duplicates.
It sorts good, but don't delete duplictates.
What's the problem?
void sort_del(List<double> slist){
//here i sort slist
//get sorted with duplicates
List<double> rlist = new List<double>();
int new_i=0;
rlist.Add(slist[0]);
for (i = 0; i < size; i++)
{
if (slist[i] != rlist[new_i])
{
rlist.Add(slist[i]);
new_i++;
}
}
slist = new List<double>(rlist);
//here get without duplicates
}
It does not work because slist is passed by value. Assigning rlist to it has no effect on the caller's end. Your algorithm for detecting duplicates seems fine. If you do not want to use a more elegant LINQ way suggested in the other answer, change the method to return your list:
List<double> sort_del(List<double> slist){
// Do your stuff
return rlist;
}
with double you can just use Distinct()
slist = new List<double>(rlist.Distinct());
or maybe:
slist.Distinct().Sort();
You're not modifying the underlying list. You're trying to add to a new collection, and you're not checking if the new one contains one of the old ones correctly.
If you're required to do this for homework (which seems likely, as there are data structures and easy ways to do this with LINQ that others have pointed out), you should break the sort piece and the removal of duplication into two separate methods. The methods that removes duplicates should accept a list as a parameter (as this one does), and return the new list instance without duplicates.
I have a set of servers for which I need the names, but I only want those that are currently available so I need a dynamically sized array. What data structure can I use to store these.
You probably want to use the the generic List<T> class, as in List<string>.
Let's say you have your server names in a comma-separated values string. Then you can use the Split and ToList() extension method (on IEnumerable) to convert it to a dynamically-sized list.
string input = "server1,server2,server3";
List<string> serverNames = input.Split(',').ToList();
Or if you are checking them one at a time using some other method.
List<string> serverNames = new List<string>();
foreach (var server in GetAvailableServers())
{
if (server.IsAvailable)
{
serverNames.Add( server );
}
}
A rough equivalent to C++'s Vector<t> in C# is a List<t>. Works as a dynamic array, allowing you to List.Add() and access it via index.
E.G.
List<string> names = new List<string>();
names.Add("John");
names.Add("Mike");
foreach (string name in names)
{
evaluate(name);
}
List<string> servers = new List<string>();
servers.Add("http://stackoverflow.com");
See msdn.
You're looking for the List<T> class.