I'm having a [Serializable] class with some properties,methods and some web controls.
Using this class i were made a Dictionary<string,object> variable.
This Dictionary variable contains various objects of my class.
Now i need to store this Dictionary variable into view-state so that i can use this Dictionary variable on every post-back of my web form.
When i use this line of code to store my Dictionary variable into view-state
ViewState[this.ClientID + "_CtrAdd"] = dictControl;
It throws error:
Type 'System.Web.UI.WebControls.TextBox' in Assembly 'System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' is not marked as serializable.
Note:
My class objects contains some web controls.
Can any one tell me how can i store this Dictionary variable into an View-state .
Your exception is realy clear about what to do. You need to store the data inside your dictonary, not the controls. Controls refrence to many objects, all these object whould have to be saved, that is why controls are not serializable. You also want to keep your ViewState as small as possible, the size will have a significant inpact on your performance.
As the error suggests, you can't store certain classes, i.e. those that aren't marked as serializable, in ViewState. This is because ViewState is stored as a BASE64-encoded string in a hidden field on the page, and as such any class that you attempt to store in ViewState must be serializable.
You would have more success building a separate class that just stores data that you need to store in order to have it available in the next postback.
Web controls will store data in view state without you needing to do anything, so perhaps your class can just store the control's ID which you can then use to reference the control later on.
For example:
[Serializable]
class MyCustomData
{
public string TextBoxID1 { get; set; }
public int MyCounter { get; set;}
public decimal MyTotal { get; set; }
}
var data = new MyCustomData { TextBoxID1 = txtMyTextBox.ID, MyCounter = anInt, MyTotal = aDecimal };
ViewState[this.ClientID + "_Data"] = data;
Related
I'm using Entity Framework (DB First) on a new project and wanted to add some customisation to the classes generated. However, my changes are obviously lost every time that the edmx is refreshed. I was just wondering if there is a design pattern for handling this sort of thing?
As an example, suppose I have a class with a integer property; StatusID - and I'd like to extend the entity class so that the status value can also be accessed/set via the related enum and finally a property that gets a text representation of that Enum from the description attribute. This all works, but those customisations are lost when the model is refreshed. I appreciate that the property can be converted to an enum, so the latter property that gets the description of the enum is perhaps a better example for this question.
I think I know the answer but I just wanted to put this out there in case there were some magic tricks that would allow this to work and prevent those customisations from being lost.
public int StatusID { get; set; }
public Enumerations.ValidationStatus StatusEnum
{
get
{
return (Enumerations.ValidationStatus)StatusID;
}
set
{
StatusID = (int)value;
}
}
public string StatusText
{
get
{
return MyMethodThatGetsTheEnumDescription(StatusEnum);
}
}
Two Solutions to work around the problem:
User Data Transfer Object(DTO) nd put the enum there. then use Automapper or manually map between the DB Model and the DTO Model (best practice)
Instead of enum you can use extension functions on the model and define your getter, setters and any extra properties you want as extension functions to the class
(will add some complexity to your models)
class Student{
public string Name {get; set;}
public EntityCollection<Info> Infos {get; set;}
}
class Info{
public string Title {get; set;}
public Student Student {get; set;}
}
I have two entities like this. First I will query one student entity
var student = db.Students.FirstOrDefault(s => s.StudentId = 1);
Then I query Info list of this student in a separate query
var infos = from c in db.Info where c.StudentId = 1 and ....
If I loop though infos and add it manual into student.Infos, it will cause insert new row
foreach(info in infos){
student.Infos.Add(info);
}
How to attach list of info into student entity without insert new row into Info table when db.SaveChanges(). Like
student.Infos = infos
EF does the work for you behind the scenes when you use navigation properties. It's not just a data layer to load data singularly but rather it's set up with the relationships between the data and is capable of loading an entire object graph of related data either in one hit (eager loaded) or on-demand (lazy loaded)
Firstly: you can update your Info collections to ICollection<Info> or List<Info>. I opt for List<Info> because I commonly use .AddRange(). Also, mark it as virtual to enable EF proxies and lazy loading.
From there, to access the Infos on a Student you can just use:
var student = db.Students.Include(s => s.Infos).SingleOrDefault(s => s.StudentId = 1);
This will eager-load the Infos for the selected student. No need to load them separately.
If you leave off the .Include(..) then you can still access the Infos (provided the DbContext is still in scope) though this will trigger additional SQL calls to load the Infos. (Lazy loaded)
When loading data to send outside of the scope of the DbContext, such as returned from an API call, or sent to a view, it's recommended to compose a DTO or ViewModel with just the fields that you need from the various entities, then perform a .Select() to populate them, and return the DTOs not the entities. This avoids problems with lazy loading calls after a DbContext has been disposed and unexpected performance issues if lazy loading is triggered due to serialization or the like.
I have this class:
public class address
{
public string address1;
public string address2;
public string city;
}
Now whenever a page load I fill these values based on the session userid in parent user control,
on_load of parent page
{
connect to database;
get the info
address.address1 = "171, broadway";
}
now across the child user controls on this page I want to use these values...
address.address1 and so on without hitting database again, this is a sample data actual data is long enough to use session.
What is the best way of doing it?
Save the Data in the current session and call it every time you need
This will help Storing custom objects in Sessions
If Data is too big then just bind the data to all controls before "get the info"
Add a property called Address to each UserControl that should have access to this data. Then in the parent UserControl, set this property for each control.
I'm creating a shopping basket in ASP.NET using session variables to pass the data from a shopping.aspx page to basket.aspx, currently I have the pages passing the primary key of the product with a gridview on the basket.aspx used to display the data from the database.
However this only works for one item at a time, how can I extended the session variable so multiple products can be added, as well as quantities etc?
You can use your own object, eg. Basket which can have one or more properties.
Object should be market as Serializable.
For example:
[Serializable]
public class Basket
{
public List<BasketItem> Items {get;set;}
public int UserId {get;set;}
}
[Serializable]
public class BasketItem
{
//...
}
You can put (almost) any object into the session, not just strings. So you could use a List<string> for a list of keys, or even a List<Product>.
EDIT
So in the first page you would get
var bookids = new List<string>();
// collect all book IDs into the 'bookids' list
Session["bookIDs"] = bookids;
and in the second page:
var bookids = Session["bookIDs"] as List<string>;
// use all IDs
I'm looking for some ideas to best persist an object over multiple page requests without the use of session variables, cookies, context cache, view state or a session database.
I have a web form (ASPX) that will contain several user controls that will act as "pages", and these controls will be displayed in a one-at-a-time-manner:
<uc1:UserControl1 id="controlStep1" runat="server" visible="true" />
<uc2:UserControl2 id="controlStep2" runat="server" visible="false" />
<uc3:UserControl3 id="controlStep3" runat="server" visible="false" />
I have an object that I use to contain various parameters. These parameters come into the application as query string values and this object lazy loads them. For example:
public class Situation
{
private string _jobId;
private JobType _jobType;
public string JobId
{
get
{
if (!String.IsNullOrWhitespace(_jobId))
return _jobId;
_jobId = GetFromQueryString("jid");
return _jobId;
}
}
public JobType JobType
{
get
{
if (_jobType != JobType.Default)
return _jobType;
_jobType = GetEnumFromQueryString("jtype", typeof(JobType));
return _jobType;
}
}
}
I'd like to persist this Situation object while the customer is in the web application, proceeding through a wizard-style interface as the user controls' visibilities are toggled. At the moment, I'm creating an instance of the Situation object in an HttpModule during the customer's first request and storing it in HttpContext.Current.Items, but I'd like to use lazy loading so that the various Situation object properties are only loaded as needed. However, if for example a property is accessed on controlStep1, I'd like to persist the state of the object so that if that same property is accessed on controlStep2, the getter doesn't have to go back to the query string to get the requested property's value. I could serialize the object and deserialize in an HttpModule, but if a property is accessed and loaded, it wouldn't be remembered on the next request.
Any suggestions?
File system is sometimes a useful persistance mechanism.