Reading Session value in View MVC - c#

I have a Session in my Controller as follow
Session["Fulldata"] = data;
Which stores data like Name,Id,City etc;
It stores multiple rows of such data.
How how do I access or check if any row has particular Name in it, in the View?
eg :
#if(Session("Fulldata").has("ABC"))
{
//Do Something
}
I want to check Name for each row in Session. Any help will be appreciated

First you need to cast the Session("Fulldata") back to you type as session store your collection as object type.
List<CustomClass> data = (List<CustomClass>)Session("Fulldata");
If data is a collection you can use linq Enumerable.Any to Search
#if(data.Any(d=>d.YourAttr1 == 'ABC' || d.YourAttr2 == 'ABC'))
{
//Do Something
}
As a additional note please do not use session unnecessarily especially for big data as session will need space on your server and as user/session increase it could adversely effect the performance.

Related

Holding value between multiple pages

I'm working on rewriting an MVC application that currently utilizes cookies to hold data between multiple pages such as a date. I have tried to come up with an option that would hold the data in the controller by using something like this:
public DateTime HoldDate {get; set;}
The problem that I'm facing is that this is overwritten on each page load. I have also considered using Vue to store the variable and then sending the date to the controller on page load, but I'm not sure how to perform this.
Any help is appreciated and thank you in advance!
You can use TempDataDictionary to pass data from the controller to the view and back. It's a Dictionary, so you can access it with a key:
TempData["HoldDate"] = new DateTime(2020, 2, 13);
When you read data normally from TempData, it is automatically marked for deletion with the next HTTP request. To avoid that, since you want to pass this data around, use the .Peek() method, which lets you read the data but does not mark it for deletion.
var date = TempData.Peek("HoldDate");
If you need data to persist during the entire user session, you can use Session. For example user id or role id.
if(Session["HoldDate"] != null)
{
var holdDate= Session["HoldDate"] as DateTime;
}
If you need data only persist a single request - TempData. Good examples are validation messages, error messages, etc.
if (TempData.ContainsKey("HoldDate"))
{
var holdDate = TempData["HoldDate"] as DateTime;
}
TempData and Session, both required typecasting for getting data and check for null values to avoid run time exception.

How to Append/Add Data to an ASP.NET Session?

I have real time data coming from energy meters and I have to render this data to a table. I am a beginner and do not know how to append data to a Session. When I add data to the Session the old data gets lost.
public void Get_Real_Time_Values(Real_Time_Values values)
{
//please any guidance for appending data
Session["values"] = values;
}
if (datList.Count >= 100)
{
datList.RemoveRange(1, 20);
}
the data in Session is identified with a key. You cannot simply append data to it, but what you can do is append data to it in an indirect manner:
How?
Well, first read the data from the session into an object, list of object whatever you have, then append your new data to it then store the data back in the session.
An example would look like this:
Real_Time_Values currentSessionData = (Real_Time_Values )Session["values"];
currentSessionData.Add(newData)
Session["values"] = currentSessionData;
Be careful with how much data you store in the session though. If you have too much data you might want to start using a database or some sort of caching layer.

Fastest way to compare 2 lists objects [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I allow a user to download some data to csv. They can then edit some columns and then upload it back. I need a speed efficient way to compare certain columns between like objects to see what changed.
Currently I pull the original data from the DB and make it a list so it's all in memory. There is about 100k items so it's not that bad. That part takes less than a second. Then I load in the csv file and put it to list. Both lists have the same class type.
Then I loop over the csv data (as they probably removed some rows which they didn't change but they could still have changed a lot of rows). For each row in the csv list I query the list that came from the DB to find that object. Now I have the csv object and the object from the database as the same structure. Then I run it through a custom object compare function that looks at certain columns to see if anything changed.
If something did change I have to validate what they entered is a valid value by query another reference list for that column. If it's not valid I write it out to an exceptions list. At the end if there are no exceptions I save to db. If there are exceptions I don't save anything and I show them the list of errors.
The detail compare provides a list of columns and the old vs new values that changed. I need this to query the reference list to make sure the new value is valid before I make the change. It's fairly inefficient but it gives great detail to the user about what may be an issue with an upload which is very valuable.
This is very slow. I'm looking for ways to speed it up while still being able to give the user detailed information about why it may have failed so they can correct it.
// get all the new records from the csv
var newData = csv.GetRecords<MyTable>().ToArray();
// select all data from database to list
var origData = ctx.MyTable.Select(s => s).ToList();
// look for any changes in the new data and update the database. note we are looping over the new data so if they removed some data from the csv file it just won't loop over those and they won't change
foreach (var d in newData)
{
// find data so we can compare between new (csv) and current (from db) to see what possibly changed
var oData = (from o in origData
where o.id == d.id
select o).FirstOrDefault();
// only the columns in the updatableColumns list are compared
var diff = d.DetailedCompare(oData, comparableColumns.ToList());
if (diff.Count > 0)
{
// even though there are differences between the csv record and db record doesn't mean what the user input is valid. only existing ref data is valid and needs to be checked before a change is made
bool changed = false;
// make a copy of this original data and we'll check after if we actually were able to make a change to it (was the value provided valid)
var data = CopyRecord(oData);
// update this record's data fields that have changed with the new data
foreach (var v in diff)
{
// special check for setting a value to NULL as its always valid to do this but wouldn't show up in ref data to pass the next check below
if (v.valA == null)
{
oData.GetType().GetProperty(v.Prop).SetValue(oData, v.valA);
oData.UpdatedBy = user;
oData.UpdatedDate = DateTime.Now;
changed = true;
}
// validate that the value for this column is in the ref table before allowing an update. note exception if not so we can tell the user
else if (refData[v.Prop].Where(a => a.value == v.valA.ToString()).FirstOrDefault() != null)
{
// update the current objects values with the new objects value as it changed and is a valid value based on the ref data defined for that column
oData.GetType().GetProperty(v.Prop).SetValue(oData, v.valA);
oData.UpdatedBy = user;
oData.UpdatedDate = DateTime.Now;
changed = true;
}
else
{
// the value provided isn't valid for this column so note this to tell the user
exceptions.Add(string.Format("Error: ID: {0}, Value: '{1}' is not valid for column [{2}]. Add the reference data if needed and re-import.", d.id, v.valA, v.Prop));
}
}
// we only need to reattach and save off changes IF we actually changed something to a valid ref value and we had no exceptions for this record
if (changed && exceptions.Count == 0)
{
// because our current object was in memory we will reattached it to EF so we can mark it as changed and SaveChanges() will write it back to the DB
ctx.MyTable.Attach(oData);
ctx.Entry(oData).State = EntityState.Modified;
// add a history record for the change to this product
CreateHistoryRecord(data, user);
}
}
}
// wait until the very end before making DB changed. we don't save anything if there are exceptions or nothing changed
if (exceptions.Count == 0)
{
ctx.SaveChanges();
}
The first big win would be to put your data in a dictionary so you can get to the desired value quickly by ID, without having to search for the object through thousands of objects. I'm pretty sure it'll be faster.
Beyond that I suggest you run your code through a profiler to determine exactly which parts are the slowest. It's entirely possible that DetailedCompare() does something that's terribly slow but may not be obvious.
One thing to consider is having asynchronous compares and or asynchronous if (diff,Count > 0) at least the latter assuming that there are a few random changes why wait for all the copying and reflection. Put it in a seperatge function and have run parallel.

Best caching strategy in this particular scenario

I am retrieving a big list of news items.
I want to utilise caching of this list for obvious reasons (running a query any more than necessary won't do).
I bind this list to a repeater on which I have extended to enable paging (flicking between pages causes page load and so a retrieval of the list again).
The complication is the fact that these news items can also be queried by date from a query string 'year' that is present only when querying the news items by date.
Below is pseudo code for what I have so far (pasting the real code here would take too much time trimming out all of the bits that just add confusion):
if(complete news items list are not cached OR querystring["year"] != null)
{
Int year = queryString["year"] (could be null)
Cache.Add(GetNewsItems(year));
}
else
{
return cached newsItems;
}
The problem is that when the news items page loads (because of a paging control's postback) the querystring's [year] parameter will still be populated and so will re-do the GetNewsItems. Also - even if the home URL (i.e. no query string) is then navigated to - in effect there is still a cached version of the news items so it will not bother to try and retrieve them - but they MAY be there for a particular year and so aren't relevant to an 'all years' kind of search.
Do I add a new cache entry to flag what most recent search was done?
What considerations do I have to make here to cache timing out?
I can add a new query string if needs be (preferably not) - would this solve the problem?
Could you get the complete list on the first query, and cache this (presuming it is not too enormous)? Then for any subsequent queries get the data from the cache and query it to filter out just the year you want.
Maybe you could store the data in the cache in the form of
IDictionary<int, IEnumerable<NewsItem>>
(assuming there are more than one NewsItem for a year) where the key is the year so you can just retrieve a single dictionary value pair to get a year's data.
Alternatively cache the data by year, as you are doing in your sample, and implement a mechanism to get data from the cache for each year if it exists. When getting all, you can either just get all from the data store and cache this separately or implement some mechanism to determine what years are missing from the cache and just get these. Personally, I think I would go with caching all and filtering data from the cache so as to not clog up the memory with too much cached data.
A useful TryGetValue pattern to get from cache is something like:
private bool TryGetValue<U>(string key, out U value)
{
object cachedValue = HttpContext.Current.Cache.Get(key);
if (cachedValue == null)
{
value = default(U);
return false;
}
else
{
try
{
value = (U)cachedValue;
return true;
}
catch
{
value = default(U);
return false;
}
}
}
Not sure if this might help for your case, but you can add the repeater to an user control, and enable OutputCache for it, to be invalidated by POST/GET params:
<%# OutputCache Duration="100" VaryByParam="year" %>

Accesing Server Control from other webform

I have 2 webforms with 1 ListBox Control on each of them.
How do I access the Listbox that's located on webformA from webformB?
For example I wish to declare something like this string name = ListBoxWebformA.SelectedValue.ToString(); on WebFormB, so that I can work with that value in the code of WebFormB.
The ListBox on WebFormA lists several names.
When I select a name from the listbox and press the OK button I call Response.Redirect("~/WebFormB.aspx");
So from WebFormB I wish to access this "name" by putting the selected value into a string.
Based on your edit, the easiest (possibly best) way to go about doing this will not be to try to maintain a stateful instance of webformA during the request to webformB. Once the user is redirected, assume that webformA is gone.
Instead, when you're about to perform the Response.Redirect() to webformB, include in some way the value from webformA that you wish to pass along. The easiest way to do this will be on the query string. Something like:
Response.Redirect(string.Format("~/WebFormB.aspx?name={0}", HttpUtility.UrlEncode(ListBoxWebformA.SelectedValue.ToString())));
Then, in webformB you can access the value:
string name = Request.QueryString["name"];
Note that you'll want to do some error checking, etc. Make sure the value is actually selected before appending it to the redirect URL on webformA, make sure Request.QueryString["name"] contains a value before using it in webformB, etc.
But the idea in general is to pass that value along, by query string or POST value or Session value or some other more stateful means, when redirecting from one form to the other.
I guess you have to resort to either passing the value from A to B in the query string or storing the value in Session and reading afterwards.
So would be a
Response.Redirect(string.Format("~/WebFormB.aspx?YourVariable={0}",HttpUtility.UrlEncode(ListBoxWebformA.SelectedValue));
and you can read it in Form B like
Request.QueryString["YourVariable"]
If the values are not sensitive this approach above would be the best.
If they are... To store in Session:
Session["YourVariable"] = ListBoxWebformA.SelectedValue
And to read...
if (Session["YourVariable"] != null) {
var listAValue = Session["YourVariable"].ToString()
}

Categories