What is the difference in utility/performance between using PersistenceMode on a property and storing the value of said property in ViewState in an ASP.NET web page?
This:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[PersistenceMode(PersistenceMode.InnerProperty)]
public int ClientUno { get; private set; }
versus this:
public int ClientUno
{
get
{
if (ViewState["ClientUno"] == null) return 0;
else return (int)(ViewState["ClientUno"]);
}
set { ViewState["ClientUno"] = value; }
}
I have done some googling around the internets and can't figure this one out. It seems like this would have come up before - I just can't find the answer. Anyone?
PersistanceMode has nothing to do with storing data in a ViewState. It is used to create custom server controls and affects server code.
For example see: How do I make a control with a child control collection in ASP.Net
Related
can someone please explain me the code written below
public IList<GetProductPrice> CurrentPage
{
get { return ViewState["CurrentPage"] as List<GetProductPrice>; }
set { ViewState["CurrentPage"] = value; }
}
It is called a Property. They generate a getter and setter functions when compiled:
List<GetProductPrice> GetCurrentPage(){
return ViewState["CurrentPage"] as List<GetProductPrice>;
}
void SetCurrentPage(List<GetProductPrice> value) {
ViewState["CurrentPage"] = value;
}
//i think its actual get_.. but it doesn't matter for the example
So its generates ease of use getter setters. which you can just call by using:
var test = CurrentPage; //compiled to var test = GetCurrenctPage();
CurrentPage = test; //compiled to SetCurrentPage(test);
If you leave the getter and setter empty like this:
public int CurrentPage
{
get;
set;
}
it will also generate a backing field on the class where it stores the data:
private int _currentPage;
public GetCurrentPage(){ return _currentPage }
public SetCurrentPage(int value) { _currentPage = value }
Why do we do this?
Using getters and setters is a very old best practise from java (where ide's would have an option to generate them). But this would lead to a lot of boilerplate code!
In C# they try to counter this by adding these properties. But why do we need getters and setters? For example if you want to be notified when a value changes (to mark the classes it self as dirty). I think entity framework uses it to track if a model is changed otherwise it wont do a db update call. There are also other usefull tools that inject code in properties on compile time. to add extra functionality.
How not to use it:
using properties to return HttpContext.Current Is a dangerous one because you secretly depend on the HttpContext so try not to do this at any time!
Generally its also bad practise to use it when the code inside the get or set is very heavy (very instensive). Its bad practise because someone else using the code might think he is just setting a property/field while actually some very heavy code is executed. its best practice to make a special function for this instead and private the getter/setter:
public int Property {get; private set; }
public SetProperty(int value){
//intensive code here:
Property = value;
}
This property is letting the consumer of the property to use it like Local collection without referring the ViewState in the code. It will make the code simple and easy to use.
get { return ViewState["CurrentPage"] as List<GetProductPrice>; }
Here the ViewState object ViewState["CurrentPage"] is converted to list of GetProductPrice
set { ViewState["CurrentPage"] = value; }
Here the List is assigned to ViewState["CurrentPage"]
This code will only work in a controller, where ViewState is a property. This CurrentPage property provides a statically-typed way to access a certain ViewState item through that property.
So instead of sprinkling ViewState["CurrentPage"] as List<GetProductPrice> all over your controller code where you want to access the "current page", you can now simply use the CurrentPage property.
Of course "current page" is a term made up by the developer who chose to name things like this, I don't see how a List<GetProductPrice> has a relation to the "current page".
I am trying to pass a few parameters between two web pages
within the source page I have the following properties
private string _testString { get; set; }
public string TestString
{
get
{
return _testString;
}
}
In previous msdn examples the return type was always set to a UI element (textbox.text)
However I am trying to pass the value from a dynamically generated link button which is why I chose to use the private accessor
In the click event of the link button on the source page I have the following:
protected void RenderReportInNewPage(LinkButton lb)
{
_testString = lb.CommandArgument.ToString();
Response.BufferOutput = true;
Response.Redirect("~/stuff/testviewer.aspx");
}
On the target page I have the source page referenced in the aspx as follows:
<%# PreviousPageType VirtualPath="~/stuff/testviewer.aspx"%>
And then in the codebehind of the target page I have the following:
Textbox.Text = PreviousPage.TestString;
PreviousPage displays the public property TestString but it is always null (as I don't think it is getting set but not sure why)
Is is possible to set a private accessor (_teststring) and have that value reflected within the public property? I'd appreciate any suggestions on what I have done wrong.
-Cheers
Found the error. It was not in the setting of the property but in how I was invoking the target page. In order to pass the properties across I needed to user Server.Transfer instead of Response.Redirect
protected void RenderReportInNewPage(LinkButton lb)
{
_testString = lb.CommandArgument.ToString();
Response.BufferOutput = true;
Server.Transfer("~/ReportBuilder/viewer.aspx");
}
-cheers
I have a WCF webservice, that exposes these classes:
[DataContract]
public class TemplatesFormat
{
List<DynAttribute> _dynsattributes = new List<DynAttribute>();
[DataMember]
public List<DynAttribute> DynsAttributes
{
get { return _dynsattributes; }
set { _dynsattributes = value; }
}
}
[DataContract]
public class DynAttribute
{
string _key = "";
string _val = "";
[DataMember]
public string Key
{
get { return _key; }
set { _key = value; }
}
[DataMember]
public string Value
{
get { return _val; }
set { _val = value; }
}
}
Basically, 2 classes. DynAttribute with 2 string attributes and TemplatesFormat, with an attribute that is a List of DynAttribute class.
So far, so good.
But, when I reference the web service from an ASP.NET web page and try to use the TemplatesFormat, I can't see the List attribute.
I mean, I actually "see" it, but it is not a list (does not contain an "Add()") and I don't know how to use it.
I think I am missing something related with de [DataContrat] and the fact that it is a custom type, since, I don't have the same problem with DynAttribute class (I see the Key and Value attributes because they are strings) but, I can't get it right for the List...
Any idea???
When you add reference to wcf service you need to change Collection Type to Generic List.
Please see my post wcf-proxy-returning-array-instead-of-list-even-though-collection-type-generic for more details and snipp picture.
WCF is meant to support consumption by many other platforms. Because List<DynAttribute> is not a primitive type, it is likely converting it to DynAttribute[].
In your consuming application. Try taking your variable and seeing if you can .ToList() it to turn it back into the List<DynAttribute> you're expecting.
NET Experts,
I got an ASP.NET MVP (Model View Presenter) application, where I am using GenMaster.Master (Master Page), Metadata.aspx (Start Page), Global.asax etc.
I am accessing the Session["EncryptedQuery"] in both GenMaster.Master (Master Page) and Metadata.aspx (Start Page).
Our Session declaration convention is to use property as follows:
public string EncryptedQuery
{
get
{
object SessionObject = Session["EncryptedQuery"];
return (SessionObject == null) ? String.Empty : (string)SessionObject;
}
set
{
Session["EncryptedQuery"] = value;
}
}
Now, where should I declare this Session property to access it in Master as well as all the content pages? And I do not want to assign/retrive to/from Session["EncryptedQuery"] direcly.
Thanks
A MasterPage is implemented as a Child Control of your Page. You should be able to access it using Page.Session from the MasterPage.
I just noticed you may have been asking is where to assign the property, rather than where to declare it. So, if you're asking what is the best practice as far as where to initialize Session data, then the answer is going to be the PostAcquireRequestState event of the HttpApplication class. You can declare this in either your Global.asax, or wire it up with a custom HTTP module.
This sort of strategy works well and allows for session data access from anywhere in the site in a strongly typed manner.
public static class SessionData
{
private const string ENCRPYTED_QUERY = "ENCRPYTED_QUERY";
public static string EncrpytedQuery
{
get
{
if (HttpContext.Current.Session != null)
return HttpContext.Current.Session[ENCRPYTED_QUERY] as string;
return null;
}
set
{
HttpContext.Current.Session[ENCRPYTED_QUERY] = value;
}
}
//add more down here...
}
We have developed a number of ASP.Net server controls and we need to test them. I want to instantiate a control, set some properties, call CreateChildControls and test the control-hierarchy.
I run into a number of problems:
The controls rely on HttpContext
CreateChildControls is private
Even adding a single child control to the controls collection calls the ResolveAdapter() method which relies on HttpContext.
How can I get around this?
p.s. I do not wish to test the controls on a page (!).
It sounds a lot like you don't care about the actual rendering of the control at all, but rather the logic contained within the control. For that I would suggest that you have another problem besides the inability to test the control outside the HttpContext.
If the logic only pertains to the control, then you should trust the framework to do it's job, and drop the control on a page to see if it works properly. If the logic you are attempting to test is business logic, then you need to refactor.
Pull out the business logic into a seperate Project/Dll somewhere, and think about implementing a MVP pattern with your server control. You don't have to go with a big heavy framework like WCSF either. Conceptually you can implement this with little effort.
Create an interface that represents the values on your view:
public interface IOrderView
{
Int32 ID{get; set;}
String Name{get; set;}
List<Item> Items {set;}
}
Once this is defined, you need a presenter that exercises this view:
public class OrderPresenter
{
public IOrderView View {get; set;}
public void InitializeView()
{
//Stuff that only happens when the page loads the first time
//This is only for an example:
var order = Orders.GetOrder(custId);
View.ID = order.ID;
View.Name = order.Name;
View.Items = order.Items;
}
public void LoadView()
{
//Stuff that happens every page load
}
}
Now your server control can implement this interface, and initialize itself with the OrderPresenter
public class OrderControl: Panel, IOrderView
{
private OrderPresenter Presenter{get; set;}
public OrderControl()
{
//Create new presenter and initialize View with reference
// to ourselves
Presenter = new OrderPresenter{View = this;}
}
protected override void OnLoad(EventArgs e)
{
if(Page.IsPostback)
{
_presenter.InitializeView();
}
_presenter.LoadView();
//Other normal onload stuff here...
}
//Now for the interface stuff
public Int32 ID
{
get{ return Int32.Parse(lblOrderId.Text); }
set{ lblOrderId.Text = value.ToString(); }
}
public String Name
{
get{ return lblOrderName.Text; }
set{ lblOrderName.Text = value; }
}
public List<Item> Items
{
set
{
gvItems.DataSource = value;
gvItems.DataBind();
}
}
}
And there you have it! You should be able to write unit tests against the OrderPresenter now using a stubbed out View. No HttpContext required, and you have cleaner seperation of concerns.
If you already have all your business logic seperated out then I appologize, but I can't think of any other reason to test a server control outside the ASP.Net runtime besides needing to verify actual business logic. If this is the case, then I would highly encourage you to refactor now before you realize the maintenance nightmare this will eventually cause via Leaky Abstractions.