c# + WebForms + static -- what are the best practices? - c#

I'm definitely not a fan of WebForms, I prefer in the .NET world ASP.NET MVC.
Regardless, I'm working on a small part of a very large legacy WebForms application.
I'm integrating Korzh.com's EasyQuery.NET. to allow end users to create their own SQL queries based on pre-defined models made user friendly with aliases.
This is relevant because Korzh's demo uses Global.asax for its model and
query class along with Session.
Because the legacy WebForms application is very large, Global.asax in not used
for page specific items.
My solution was to use private static instead. static works well in desktop
applications but seems at the very least likely to cause some grief in WebForms applications.
I've discovered that !IsPostBack is not too reliable and it seems to me that
in WebForms the best practice may be to use Session. The problem with
Session is that it seems to be passed to the client with the HTML and can grow
very large in kilobytes.
QUESTIONS:
Since static variables reside on the IIS server when used with WebForms, does every user of a WebForms application share the same static variable address space? (I think the answer is yes).
What are the best practices/guidelines for using/not using static variables
with ASP.NET WebForms applications?
Thank you.
Regards,
Gerry (Lowry)
P.S.: I could not find answers
via Google or searching SO.

In ASP.NET, static instances will live for the lifetime of the application, that being the web application itself, until it is recycled, or shutdown, e.g.:
public class Global : HttpApplication {
public static string MyString
}
Because of this, the static property is accessible for all requests made to the application. Not the place to be storing page-specific items. There are quite a few storage mechanisms available:
HttpRuntime.Cache and HttpContext.Cache, both point to the same cache instance, and items exist for the lifetime of the application (so has the same issues as static instances).
HttpContext.Items, a request specific collection of items. Each request made to the application will have its own collection of items.
HttpSessionState session, persisted for the length of the user visit, or whenever it times out. This can be configured 4 ways:
3.a. InProc, session objects are stored in memory by the worker process itself. Fast accessing cache, doesn't require serialisation, but if the application recycles, the session data is lost.
3.b. SqlServer, session objects are serialised and stored in a Sql Server database. Requires all session-stored items to be serialisable. Session objects persist even when an application recycles.
3.c. StateServer, session objects are stored in a seperate process, and persists data through application recycles.
3.d. Custom session provider, that's up to you....
ViewState, this is where data is persisted to the client-side and is posted back to the server to rebuild control states between page views.
I would avoid using static instances and the HttpRuntime cache for anything user related. Use these mechanisms for shared, common information, such as configuration, caching, etc. Session is likely the place you want to store things on a per-user basis. If you are looking for a per-page solution, its a lot simpler, because you simply make the variables part of the page structure itself, as properties or fields. You just have to manage the initialisation of these fields.
Hope that helps.

Related

How are ViewStates accessible everywhere without being declared?

I was always under the impression that to access a variable in multiple methods, you'd either have to declare it as a class member or pass it in as an argument.
However, I was looking over some sample code recently to learn .NET, and I came across something called a ViewState. I understand it's meant to track some Pages and Control Properties, but I don't understand how it's being used here.
The code looks somewhat like this:
private void RowValidating(object sender, EventArg e) {
ViewState[Backup] = ViewState["TestId"];
// more code that does not include ViewStates
}
private void UpdateBox() {
// some code that does not include ViewStates
int box_id = ViewState[Backup];
// ...
}
How is ViewState accessible everywhere? It is not declared anywhere in the class or in any of the other class files, and this [Backup] key is just sort of created without initializing it. As far as I can tell, ViewState[Backup] does not exist until RowValidating is called.
Would it be possible to set ViewState as a global variable? Or could I always just make my own key that is accessible anywhere? It seems to behave like a dictionary, but I thought the notation was dict.Add(item, value), not dict[item] = value when working with a new item. It must be initialized somewhere, perhaps in some imported library?
Both Session() and ViewState are and can be used to persist values in your code. You don't have to declare them, they are built in features of asp.net
Session() is per user and thus is often used to persist values or even pass values between pages. However in some cases ViewState is preferable.
So for example if you have a productID or maybe even a house you are about to buy? Well, if you have two tabs open or even two different browsers open then Session() applies to all instances of the browser(s) in question open. So if a user has two seperate browsers opened, then the "ID" value you persist in session() will apply to both (so, be carefull, which house ID are you about to buy when you have 3 browser pages open to 3 differnt houses open? So session() is global to the user.
So for say "persisting" a row of data to pass to the next web page/form, Session() can be great - but keep in mind it is shared among all pages opened and in operation by that user. So session() is still per user - but global to that user.
Session() can be server "in memory" (the default). However, if you are using a server farm, then each of those multiple servers can't share their memory, and as such you have to adopt what is called SQL server based session. So in place of holding these values in memory, the session() state is shuffled from a serialized "blob" stored in SQL server. So if you hosting your site say on a cloud based system like Azure (as opposed to regular hosting), then session() can't persist on these so called "large services" based systems (or you are using a server farm with load balancing in which you have multiple-servers hosting the site for scalability reasons). Since multiple copies of the hosted web site can exist at the same time, then a means to have a common session() is required (so they shove a blob thing into SQL server). So you can still use session(), but it actually stored in sql server. It is noted that in some cases session() based on SQL server can cost performance. As high as 10% - perhaps a bit more. I find that in most cases you not notice this performance hit. But it works seamless() and in fact adopting SQL server based session will mean that session() is not frequent lost due to site execution errors. I had all kinds of issues with a site losing session(). If the web hosting and management system puts the server to sleep, or even .net code errors occur, it can (and will!!) often cause a application pool re-start - and that blows out session() (but not with SQL server based ones - they are rock solid).
ViewState is often preferred since it is by EACH NEW web page. And this is stored 100% in the browser. So to persist that houseID or product you about to purchase, then this occurs by page, and not all web pages in use by the user (so in this case, VieweState would be a far better choice). ViewState is thus stored by the browser and is much the SAME mechanisum used when you enter bunch of values in text boxes, and then do a post back. The web page travels up to server - page is processed and sent back down. But you will notice that MOST controls on the page retain their value. To achieve this then ViewState is used. And this applies to hidden text boxes (or hidden fields - much the same as a hidden text box). So this encrypted blob lives in the browser client side. And this blob thing thus goes along for the post-backs and round trips to keep those controls values in-tact.
So you can use session(), or ViewState But, as noted, you don't want to stuff too much into that ViewState, since it becomes part of that round trip life cycle. But ViewState as noted is often preferred since it is per page operation. However, since each new browser page opened creates a new local per page ViewState? Then ViewState can't as a general rule be used to pass values between web pages like Session() can.
However, you CAN pass all values of all controls to the next page. You can do this by using the post-back URL of a button. When you do this, then on FIRST page load, you can use the page.previous property in the on-load event. This will give you use of ALL values from the previous page - and you don't need Session() to do this. You can also use page.Previous if you do a server.TransferRequest as opposed to a Response.Redirect().
Last but not least? You see a lot of sites have a whole bunch of parameters in the URL. So this is often used and has a long history of use. Of course users can mess and change with these values - but they are still often used and often make the URL's rather ugly. For this reason I do like asp.net sites, since then URL's don't expose a bunch of stuff in the URL as parameters and keeps such information out of site and mind. You see a lot of shopping site still using parameters and values in the URL - and they do this for reasons of scalability - (they don't have to store the persisting values server side - it saves resources).

ASP.NET share same session with .aspx page in IFream

I have an MVC application, where one controller returns a View that have an iframe , controller also returns url that need to loaded.
I need that iframe to load legacy .aspx pages.
Now I want to share some data from MVC controller to that .aspx page via 'SESSION' or 'Request' object.
Is it possible ? Do I have any other alternative to share data securely (I don't want to pass as get parameters).
Since we are talking about two different applications, there are some options but none through SESSION
Your first issue is how to identify the same user. There are two options here.
Through the use of cookies, if both applications are in the same domain. You can store a session identifier there and it will be sent to both applications. A jwt token would do fine or any other session identifier
Through the use of a single sign on system. This would be more tricky to implement and there are a lot of oauth/openidconnect systems out there to choose from.
Now onto the session iteself. Since we are talking about two applications, you are going to need some kind of shared place to store the session values
The simplest form would be a shared database where you store the session values. It could be in memory tables in mssql to speed things up. On the downside, you should be careful to invalidate/update the values which would cost in queries
Some kind of distributed cache, like REDIS.
Warning - You might see suggestions to use session state store. This is to share SESSION between servers and not so easily between applications, so I wouldn't suggest that.

Passing Complex Object correctly without using TempData / ViewBag / ViewData

For a website, consider this scenario:
Users input data, including a ID, and submit
A related controller will handle the request. At this point, one complex object will be created (by calling web services, with the ID) for a series of operations. e.g validation, etc
Return user a specific View
User input another set of data and submit
Another controller will handle this request. It requires the complex object used in step 2.
and so on...
Currently, in step 5, I will use the ID to call the web service again for getting the required complex object.
Is there any correct/efficient way, without using TempData/ViewBag/ViewData, so that I can reuse the complex object, once it is created, in step 2?
Edit:
Session is not allowed as well.
Normally, for web application, there're multiple options to store complex object depending on your need. I don't think there is a BEST way of doing, only the most suitable way and every solutions will come with PROS and CONS
SERVER SIDE
Session (I know you said cannot use session, but I just want to include it anyway): first option comes to mind, suitable for most web application. Since the modern web development are more on STATELESS, a lot of people want to avoid using Session at all cost. However, there're some specific infrastructure configuration to support session in STATELESS application such as distributed session or sticky session or you can save the session in a dedicated server or database.
PROS: easy to use, support web application naturally
CONS: need to configure a lot of things to work with STATELESS application
ANOTHER Dedicated server (Before anyone ask, I put it in the SERVER SIDE section even though it's another SERVER, but to me, whatever in our control is SERVER SIDE): a few options for you to choose here, first option could be to set up a cache server (Redis?) and retrieve/save using key (similar to session), or you can simply write an application to retrieve/save using your own logic.
PROS: reusability, extendability, works with all applications not just web, have its own scope
CONS: difficult to setup
Database: not a obvious choice, but database do support this kind of requirement
PROS: reusability, extendability, works with all applications not just web
CONS: performance issue
Other in-memory options (TempData, ViewBag, etc):
PROS: easy to use, well-supported with ASP.NET MVC
CONS: somtimes it's hard to pass around multiple views
CLIENT SIDE
There are so many options here to choose like use hidden fields, cookie, localStorage, sessionStorage, etc or even a simple query string will work
PROS: speed (since you don't need client-server transportation)
CONS: security (you cannot trust anything from client-side), not doing well with too complex object (heavy object), security (sensitive data), etc
SUGGESTED SOLUTION
I hope I understand your issue correctly but in my opinion, you should not store complex object, simply store the ID of the complex object in place of your choice, and make a query every time you need the object. So that your object is always up-to-date and you don't waste resource to store the complex object.
Hope it helps you.
If you want to project an object to a certain view, then forget about any storage (TempData/ViewBag/ViewData/Session) and then post the same object to another controller, the best way you can re-construct your object is to store the object's properties as hidden <input> controls.

How to properly share an object in my controller between methods with ASP .NET MVC?

I'm working with ASP.NET and I want to load once a big object (specific by user) in my controller and then use it in my view.
I though about a static property but I find some problems with it.
See : Is it a bad idea to use a large static variable?
I'm not familiar with this language and I have no idea how to properly share the same object between the different methods for each user. Could you tell me how to do that ? Do you know if singleton could be a solution ?
A singleton won't help you here if this big object is going to be different for every user.
Without knowing all the details, I'd say perhaps your best option is to store it in the Session object,
HttpContext.Current.Session["bigObject"] = bigObject;
Depending on the size & traffic, this can have performance problems, so I'd suggest you read up on the pros and cons of using Session
If you want to get to use something for the next simultaneous request, then use TempData - which is a bucket where you can hold data that is only needed for the following request. That is, anything you put into TempData is discarded after the next request completes.
If you want to persist the information specific to user, then go for Session. With session, you will have timeout, so that after certain amount of time the data stored in session will be lost. You can configure this value to much more bigger value. Apart from that when you go for Webfarm of servers, then maintaining session will be a problem, probably you might need to go for managing session in SQL Server or in some other store.
Alternatively you can Use Runtime Cache object in ASP.Net MVC to keep all the common data. Cached data can be accessed fast and we have other benefits like expiring cache etc. You can share this Cache object across users, or you can maintain different cache objects for different users, that is purely dependent on your logic. In case of webfarms, yo u have distributed cache servers like redis, Azure Cache service etc., which you can use them.

Why use isolated storage in an ASP.NET application?

I need to store user preferences on a per page basis in my application. For example, several pages use a custom grid pager control that needs to keep its current page size between postbacks. Most of the settings don't need to persist once the user leaves the page, but in some situations they do need to be restored. Note: Session is disabled in this application and will not be used.
I did some reading on isolated storage and understand that it can be used to store these user settings. Obviously cookies have been around a long time and are a proven approach to this scenario, but what about isolated storage? Is it going to work for all browsers and in all environments? Are permissions a problem? Does it require configuring anything on the end-user's side? Just how widely used is it? Why should one use isolated storage in an application for the given example?
Thanks!
Obviously cookies have been around a
long time and are a proven approach to
this scenario, but what about isolated
storage? Is it going to work for all
browsers and in all environments?
Ah - .NET isolated storage is SERVER SIDE. Like a database. It is meant as a small way to store small amounts of data( ONE user, not all users, viewstate) on the side the .NET application runs (in asp.net case = the server).
As such it is totally irrelvant to your question.
Put the data in a database. I know of VERY few usages of isolated stoage for ASP.NET applications, it craetes a TON of long term problems. It is not meant for server side apps.
You can always use hidden form field variables on a per-page basis, as a way to keep track of that page's state.
This is my preference to a session state strategy to deal with the scenario of users having say 2 FireFox browser instances open to the same page. No need to deal with session state issues in that scenario.

Categories