Adding to a Session ASP.NET C# - c#

I would like to add a Session["i"] with more results
currently it will only shows one set of results
e.g. School1 11/10/2011 14/11/2011 GCSE AAA
I would like to add more sets but they do not seem to be getting stored in the Session
e.g.
School1 11/10/2011 14/11/2011 GCSE AAA
School2 11/10/2012 14/11/2012 ALevels AAA
Education addResults = new Education(schoolName, fromDate, toDate , qualification , grades);
Session["i"] = (addResults );
//schoolarraylist.Add(addResults );
foreach (Education currentschool in schoolarraylist)
{
Session["i"] = currentschool.Schoollocation + "," + currentschool.Datefrom + "," + currentschool.Dateto + "," + currentschool.Qualifications + "," + currentschool.Grade + "<br />";
string tmp = Session["i"].ToString();
string[] sb = tmp.Split(',');
string [] ii = new string[sb.GetUpperBound(0) + 1];
for (int i = 0; i <= sb.GetUpperBound(0); i++)
{
ib[i] = (sb[i]);
}
foreach (string j in ii)
{
Response.Write(ii);
}
}

You can assign list of object to session and later get it back. But you should not put data in seesion without need. Session are maintained on server side for each user and putting data in session takes memory of server and it is could degrade the performance of the application. Its worth reading about sessions before using them.
List<string> lst = new List<string>();
Session["i"] = lst;
Getting list back from session object.
List<string> lst = (List<string>)Session["i"];

The Problem is, that you assign something to Session["i"] and when you try to add something to the session, you actually overwrite your previous value. In order to add objects to the Session, you either have to chose another name e.g. Session["j"] or wrap some sort of container around your objects (List, Array, Dictionary, etc.) and store that container in your Session.
Also try to find better names for your Sessions, if you take a look at your code at a later point, you probably won't know what Session["i"] is actually supposed to be.

You can also use a ArrayList :
ArrayList list = new ArrayList();
foreach (Education currentschool in schoolarraylist)
{
list.Add(currentschool.Schoollocation + "," + currentschool.Datefrom + "," + currentschool.Dateto + "," + currentschool.Qualifications + "," + currentschool.Grade)
}
Then loop through the arraylist and display in whatecver format you want to display

Related

C# return linq result as a list from a wcf service method then use it in aspx web forms page

I'm a newbie in C#
I'm trying to use a wcf service application which references a data entity model to select a row from a table.Searching s.o. I found a way to return linq query results as a list though I haven't found a way yet to use the list in my aspx web forms page.I don't know how to load the list in the aspx page and so far my research in msdn hasn't helped me.
I tried to express my problem the best way I could so you would understand, here is my code:
the wcf service application code:
public List<string> getAccountInfo(int uid)
{
List<string> result = new List<string>();
try
{
using (paragon_db_Models.user_accounts_Model context = new paragon_db_Models.user_accounts_Model())
{
var query = from uacc in context.user_accounts
where uacc.user_account_id == uid
select uacc;
foreach (var c in query)
{
string row = c.user_account_id + ";" + c.order_id + ";" + c.order_state + ";" + c.estimated_cost + ";" + c.instance_form + ";" + c.time_scedule + ";" + c.invoice + ";" + c.notification + ";" + c.user_account_type + ";" + c.username + ";" + c.password;
result.Add(row);
}
}
return result;
}
catch (Exception)
{
return result;
}
}
the aspx.cs code
protected void Page_Load(object sender, EventArgs e)
{
accountInfo_Ref.IaccountInfoSrvcClient accInfoClient = new accountInfo_Ref.IaccountInfoSrvcClient();
int id = (int)Session["UserId"];
List<string> columns = new List<string>(accInfoClient.getAccountInfo(id));
id_lbl.Text = columns[0];
order_id_lbl.Text = columns[1];
}
The service works fine. I'm also open to suggestions to better ways to do this.
Or you could not return strings from your service, you could return a list of objects.
If you MUST return strings you must split the serialized data using the String.Split method but this is really a poor method.
If you MUST return strings you could at least use a better serialization strategy such as JSON or XML.
But really consider changing your service interface.
Now let's get back to using your results:
you are using a service to return a List of records with that ID
i assume that the ID is unique and you will allways get 0 or 1 results in your list
each "row" added to the list contains the information about an account
so each row must be splitted to get the information
Code:
protected void Page_Load(object sender, EventArgs e)
{
accountInfo_Ref.IaccountInfoSrvcClient accInfoClient = new accountInfo_Ref.IaccountInfoSrvcClient();
int id = (int)Session["UserId"];
List<string> rows = new List<string>(accInfoClient.getAccountInfo(id));
// display the first row
string row = rows.FirstOrDefault();
if (String.IsNullOrEmpty(row))
{
// record cannot be found
}
else
{
string[] details = row.Split(';');
id_lbl.Text = details[0];
order_id_lbl.Text = details[1];
}
}
the method is returning a List<string>.You just have to store it in an instance of List<string>.
You have to do like this:
List<string> columns = accInfoClient.getAccountInfo(id);
UPDATE:
it is returning an array as you said in comments:
string[] columns = accInfoClient.getAccountInfo(id);
or use implict variable:
var columns = accInfoClient.getAccountInfo(id);
If i understood your question properly Simply write like this
List<string> columns = accInfoClient.getAccountInfo(id).ToList<string>();
You will get list filled with data.

Assign the entire QueryString to a String?

I've passed a really long Query String from one page to another in my Windows Phone 8 project.
I need to pass these parameters from the new page to another page but don't want to reconstruct he entire QueryString.
Is there a way to assign the entire QueryString to a new String?
Something like
String newQuery = NavigationContext.QueryString.ToString();
I need to pass these parameters from the new page to another page but
don't want to reconstruct the entire QueryString
Why not? This is programming: do all the work in one place so you don't have to do it again later. Let's use an extension method to do this.
Silverlight
Place this code in a static class...
public string ToQueryString(this IDictionary dict)
{
string querystring = "";
foreach(string key in dict.AllKeys)
{
querystring += key + "=" + dict[key] + "&";
}
return querystring;
}
Use it like this...
string QueryString = NavigationContext.QueryString.ToQueryString();
ASP.NET
When I originally read this question, I thought it was for ASP.NET, not Silverlight. I'll leave the ASP.NET answer here in case someone stumbles across it looking for how to do it in ASP.NET.
public string ToQueryString(this NameValueCollection qs)
{
string querystring = "";
foreach(string key in qs.AllKeys)
{
querystring += key + "=" + qs[key] + "&";
}
return querystring;
}
Use it like this...
string QueryString = Request.QueryString.ToQueryString();
There is something that already exists for ASP.NET. But I feel it's important to demonstrate that you can do all the work once somewhere. Then not have to do it again. If you want to use a built-in way, something like this would work, using the Query property of the Uri class.
string QueryString = System.Web.HttpContext.Current.Request.Url.Query;
Here's a way that may be a little simpler...
You could project the results into a format of your choosing. Here's a simple example below.
I've used an IDictionary<string,string> as it is the underlying type for NavigationContext.QueryString
var test = new Dictionary<String,String>();
test.Add("1", "one");
test.Add("2", "two");
test.Add("3", "three");
// Choose any string format you wish and project to array
var newArray = test.Select(item => item.Key + ":" + item.Value).ToArray();
// Join on any separator
string output = String.Join(",", newArray);
This still means that you have to interpret the result later (according to the format you chose). Here you'll get a format like
"1:one,2:two,3:three"
If you've sent it as a querystring just pull it back out on the OnNavigatedTo() Method and then you can store the query in the page until you move on?.
string newQuery;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
newQuery = NavigationContext.QueryString["queryName"];
}
Try this:
public string GetQueryString()
{
IDictionary<String, String> NavigationContextData = NavigationContext.QueryString;
string data = "/Pagename.xaml?";
foreach (var item in NavigationContextData)
{
data += item.Key + "=" + item.Value + "&";
}
data = data.Substring(0, data.Length - 1);
return data;
}
If it's in your OnNavigatedTo() event, you can use a quick, easy two-liner. This can be condensed to a single line or expanded to check for the existence of the ? character. If you know that there are always parameters passed, the check is unnecessary and these two lines work fine:
string QStr = e.Uri.ToString();
string ParmStr = QStr.Substring(QStr.IndexOf('?') + 1);
You can also condense it into a single line:
string ParmStr = e.Uri.ToString().Substring(e.Uri.ToString().IndexOf('?') + 1);

LINQ results change at end of for loop

When performing a set of LINQ queries against a data-source (I'm using LINQ-to-SQL, but it happens here too using just a List<string> object), I end up getting a different result at the end of my checks.
Specifically, the code below is trying to find if a Fully Qualified Domain Name (FQDN) either exists in a list of host names (not all of which will be FQDNs or in the same domain, but the host identifier is what matters to me). The search is trying to find whether "host-6.domain.local" or any of its sub-components exist (i.e, "host-6.domain" or "host-6") in the list, which they do not. While inside the for-loop, we get the results we expect, but as soon as the for loop is finished, I get a result that has all of the contents of the list, which to me sounds like it is trying to find elements that match the empty string.
void MyMethod()
{
string fqdn = "host-6.domain.local";
string[] splitFqdn = fqdn.Split('.');
List<string> values = new List<string>();
values.add("host-1");
values.add("host-2.domain.local");
values.add("host-3.domain.local");
values.add("host-4");
values.add("host-5.other.local");
IEnumerable<string> queryResult = null;
for (int i = splitFqdn.Length; i > 0; i--)
{
result =
from value in values
where value.StartsWith(
string.Join(".", splitFqdn.Take(i)))
select value;
Console.WriteLine(
"Inside for loop, take " + i + ": " + result.Count());
}
Console.WriteLine();
Console.WriteLine(
"Outside for loop: " + result.Count());
}
Why is this happening and how can I get accurate results that I can still access after the for loop is finished?
You are getting bitten by LINQ's lazy execution and closure.
When you create an enumerable like you are doing here...
result =
from value in values
where value.StartsWith(
string.Join(".", splitFqdn.Take(i)))
select value;
It doesn't get evaluated until you do something that forces it to get evaluated... for instance when you do result.count()
Then later outside of your loop when you evaluate it again result.count() is evaluated with the last value of i that existed in your for loop which is not giving you what you want.
Try forcing evaluation by doing .ToList() on your enumerable like so... This code shows both values so you can compare.
void MyMethod()
{
string fqdn = "host-6.domain.local";
string[] splitFqdn = fqdn.Split('.');
List<string> values = new List<string>();
values.add("host-1");
values.add("host-2.domain.local");
values.add("host-3.domain.local");
values.add("host-4");
values.add("host-5.other.local");
IEnumerable<string> queryResult = null;
List<string> correctResult = null;
for (int i = splitFqdn.Length; i > 0; i--)
{
queryResult =
from value in values
where value.StartsWith(
string.Join(".", splitFqdn.Take(i)))
select value;
correctResult = queryResult.ToList();
Console.WriteLine(
"Inside for loop, take " + i + ": " + queryResult.Count());
}
Console.WriteLine();
Console.WriteLine(
"Outside for loop queryResult: " + queryResult.Count());
Console.WriteLine(
"Outside for loop correctResult: " + correctResult.Count());
}
EDIT: Thanks nlips for pointing out that I hadn't fully answered the question... and apologies for converting to method syntax but it would have taken longer to convert to query syntax.
void MyMethod()
{
string fqdn = "host-6.domain.local";
string[] splitFqdn = fqdn.Split('.');
List<string> values = new List<string>();
values.Add("host-1");
values.Add("host-2.domain.local");
values.Add("host-3.domain.local");
values.Add("host-4");
values.Add("host-5.other.local");
values.Add("host-5.other.local");
IEnumerable<string> queryResult = null;
List<string> correctResult = new List<string>();
for (int i = splitFqdn.Length; i > 0; i--)
{
correctResult = correctResult
.Union(values.Where(
value => value.StartsWith(string.Join(".", splitFqdn.Take(i)))))
.ToList();
}
}
I really like Kevin's answer to my question, but I wasn't a huge fan of calling .ToList() on the result since this would cause all of the objects that matched to be pulled from the database (eating up more memory) rather than executing a query that simply got the count of matching objects (which is a little faster and doesn't take the memory to store the objects), so using the information from his post, I have this additional solution that doesn't require pulling all objects from a database, and only runs a COUNT query (in the SQL sense).
To avoid the issue caused by capturing i which then becomes 0 at the end of the for-loop, I simply set up a temporary variable to hold the value I'm searching for.
void MyMethod()
{
string fqdn = "host-6.domain.local";
string[] splitFqdn = fqdn.Split('.');
List<string> values = new List<string>();
values.add("host-1");
values.add("host-2.domain.local");
values.add("host-3.domain.local");
values.add("host-4");
values.add("host-5.other.local");
IEnumerable<string> queryResult = null;
for (int i = splitFqdn.Length; i > 0; i--)
{
//taking the line referencing i out of the
//query expression prevents referencing i
//after it is set to 0 outside the for loop
string temp = string.Join(".", splitFqdn.Take(i));
//since temp isn't changed anywhere else, it won't
//get set to an invalid value after the loop exits
result =
from value in values
where value.StartsWith(temp)
select value;
Console.WriteLine(
"Inside for loop, take " + i + ": " + result.Count());
}
Console.WriteLine();
Console.WriteLine(
"Outside for loop: " + result.Count());
}
I think you need to call ToList when assigning to the result variable like this:
result =
(from value in values
where value.StartsWith(
string.Join(".", splitFqdn.Take(i)))
select value).ToList();

Unreliable parallel loop fails 4 out of 400 times

I have a Parallel foreach function that creates a new instance of a class, that manipulates a picture, and saves it to the disk...
However approximately 4 times out of 400, the picture gets saved to the disk, but without being manipulated, my theory is that when it happens, some of the propperties existing in my class is null, when they are not suppost to...
The 4 (sometimes 3) errors mostly occurs in the first 10 images of the parallel loop.
There is no error message, it justs skip some of my code, for some reason... My breakpoint doesn't work when it is parralel, so it is hard to debug.
Any advice on how to proceed / debug / fix ?
The code as requested
private static void GenerateIcons(Effects effect)
{
DirectoryInfo dir = new DirectoryInfo(HttpContext.Current.Server.MapPath(#"~\Icons\Original\"));
FileInfo[] ff = dir.GetFiles();
string mappath = HttpContext.Current.Server.MapPath(#"~\Icons\");
List<string> paths = new List<string>();
string ids = GetAllEffectIds(effect.TinyUrlCode);
Parallel.ForEach(ff, item =>
{
if (!File.Exists(mappath + #"Generated\" + ids + "-" + item.Name))
{
paths.Add(mappath + #"Generated\" + ids + "-" + item.Name);
ApplyEffects f = new ApplyEffects(effect, item.Name, mappath);
f.SaveIcon();
}
});
//Zip icons!
ZipFiles(paths, effect.TinyUrlCode, ids, effect.General.Prefix);
}
You can re-write it in a more functional style, to hopefully remove the threading issues:
private static void GenerateIcons(Effects effect)
{
var dir = new DirectoryInfo(HttpContext.Current.Server.MapPath(#"~\Icons\Original\"));
var mappath = HttpContext.Current.Server.MapPath(#"~\Icons\");
var ids = GetAllEffectIds(effect.TinyUrlCode);
var filesToProcess = dir
.EnumerateFiles()
.AsParallel()
.Select(f => new { info = f, generated = File.Exists(mappath + #"Generated\" + ids + "-" + f.Name) })
.ToList();
Parallel.ForEach(filesToProcess.Where(f => !f.generated), file =>
{
new ApplyEffects(effect, file.info.Name, mappath).SaveIcon();
});
//Zip icons!
ZipFiles(filesToProcess.Select(f => f.info), effect.TinyUrlCode, ids, effect.General.Prefix);
}
My theory is that your list of paths is not being updated properly due to List<T> not being thread safe. Essentially if two threads try and add an item to the list at the same time any number of weird things could happen, like 4 items missing from the resulting list. Try using the lock statement.
Parallel.ForEach(ff, item =>
{
if (!File.Exists(mappath + #"Generated\" + ids + "-" + item.Name))
{
lock(paths)
{
paths.Add(mappath + #"Generated\" + ids + "-" + item.Name);
}
ApplyEffects f = new ApplyEffects(effect, item.Name, mappath);
f.SaveIcon();
}
});
Have you checked with the none parallel version?
Are you using any
API functions that is not marked as thread safe?
To answer 1), mutex lock the entire function and test for errors.
To answer 2) reduce the amount of code in the mutex until you find the offending function. You can do this by bisection.
ConcurrentBag<T> Is a thread safe container.

how to get words inside a string

well i am working with xml but it is not important now, the problem is the next
it returns me something so
<xml>blalbalblal asfjñs
fasdf
iduser=dmengelblack; name=angel; lastname=uc;
blablal
iduser=cccarlos; name=carlos; lastname=uc;
how do i get (dmengelblack, angel, uc, carlos, uc)
i want to save every row...
remember all it is inside a string how do i get "dmengelblack", "angel", "uc" save it, everyone in a variable, and save all this in a variable too.. for example
string id="dmengelblack";
string name="angel";
string lastname="uc";
all="dmengelblack angel uc"
and i need to save the other row too, and all rows it can have
what do i know?
i know before than username it is "id="
i know before name it is "name="
i know before lastname it is "lastname="
i kwnow everyone finish with ";"
Simple way in java is to read the file as a stream, iterate through that and get the substring between
iduser= and ;
and
name= and ;
and
lastname= and ;
EDIT: With this code you will get the list of all the filed you want as
OUTPUT:
[iduser=dmengelblack, iduser=cccarlos]
[name=angel, name=carlos]
[lastname=uc, lastname=uc]
So now you interate through these list, split the each entry on =, you will the value you wanted at the second index on split.
CODE:
String str = "<xml>blalbalblal asfjñs" + "fasdf"
+ "iduser=dmengelblack; name=angel; lastname=uc;"
+ "blablal"
+ "iduser=cccarlos; name=carlos; lastname=uc;";
List<String> iduser = new ArrayList<String>();
List<String> name = new ArrayList<String>();
List<String> lastname = new ArrayList<String>();
int i = 1;
while(str.indexOf("iduser=", i) > 0) {
i=str.indexOf("iduser=",i);
iduser.add(str.substring(i, str.indexOf(";", i)));
name.add(str.substring(str.indexOf("name=", i), str.indexOf(";", str.indexOf("name=", i))));
lastname.add(str.substring(str.indexOf("lastname=", i), str.indexOf(";", str.indexOf("lastname=", i))));
i=str.indexOf("lastname=",i);
}
System.out.println(iduser);
System.out.println(name);
System.out.println(lastname);
hope this helps.
I would use RegEx to extract the pattern of key values into a hast table (dictionary), then use a know key mapping to assign it to the variables you have (iteration with a switch statement or something)
In c# (and other languages, but they will have different syntax) you can split a string into an array of strings like this:
string myString = "item1;item2;item3";
string[] separateStrings = myString.Split(';');
This will give you a string array like:
string[0] = "item1";
string[1] = "item2";
string[2] = "item3";
I would also suggest you clean up you tags to only tag what you really care about.

Categories