.NET Beans + request scope - is it possible? - c#

I have my web application. I need, when a user do a request (I mean, call a page) create an object that store some information (it get these from database) for each request (so the data is updated at every request) and for each user (so UserA don't share the same object regard UserB).
I use to work on Java and some Web Frameworks (like Struts, Spring and JSF) and there was possible to create these objects (JavaBeans) with scope of request, and putting them visible for the whole application. I mean :
public class iContext
{
public iContext()
{
Response.Write(myBeans.Title());
}
}
it's possible without create an Istance of MyBeans every time .
I thought to put the object on session, but I prefeer to get rid about this (in fact I should check, replace, delete or insert the object every time and done tons of queries :)).
Are there some strategies to do this kind of work on .NET 3.5 and C#?

In ASP.Net it's important to know the page's life cycle. If you understand this, you could use the HttpContext.Items[] Dictionary object to fill with your custom context class in the (pre) init phase of the page. Anywhere you load data that's important to keep in memory you can add it to your context class and use it anywhere you want since HttpContext is available at all times in the scope of your page.

Related

ASP.NET MVC: Will class members stay in memory after HTTPPost or they dispose?

I'm going to ftech list of my application admins(users with role 'admin') and store them in a List<ApplicationUser> AdminList inside a controller of a custom model and in its create action. AdminList is populated inside create action to populate a drop-down in create view.
I want to know is it possible that the list i.e. AdminList will be disposed among calling create and its postback? In other words, is it required to populate AdminList again inside postback method or dispose will never happen?
HTTP is stateless.
Unlike things like WPF applications or Winfows Forms applications, web applications don't maintain a "running application" filled with in-memory state. (At least not in the same intuitive way.) Each request builds up a new state each time. This includes, in the case of MVC, a new instance of the Controller. (Or in the case of Web Forms, a new instance of the Page.)
In order for the data to be persisted from one request to another, you'd need to persist it somewhere. "Somewhere" could be a whole host of different places. The page's form elements, cookies, session, static variables, a database, a file, etc.
For example, if this "admin list" is relatively static and unlikely to change, and is the same for all users of the site, then you might store it in a static property which gets lazy-loaded if it's not set. Something structurally like this:
private static List<ApplicationUser> _adminList;
private static List<ApplicationUser> AdminList
{
get
{
if (_adminList == null)
_adminList = GetAdminsFromData();
return _adminList;
}
}
(However you populate the list would be what that function call does, of course.)
That way the consuming code never really needs to know or care if the list has been populated or not. Just consume the AdminList property and, if it hasn't been populated (if for whatever reason the static context has been cleared, such as an application re-start) then it'll be populated. Otherwise it'll just contain whatever was last put there.

windows store application page refresh

I am new to windows store application development and currently i am developing a news application and i want to refresh the page to get news updated. i stated developing the default layout which is given to us when starting a project and i am lost with the page dictionary because once the page is created. It gets save so is there a way to refresh a page!!! LoadState method is called when application runs for the first time when refresh is clicked the view get clear but all the data is saved in the dictionary according to my knowledge is there a easy way to clear data inside the groups and recall the methods so that the new data will get filled in.can some one please guide me with the relevant steps
protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
var sampleDataGroups = SampleDataSource.GetGroups((String)navigationParameter);
this.DefaultViewModel["Groups"] = sampleDataGroups;
}
private void refresh(object sender, RoutedEventArgs e)
{
this.DefaultViewModel.Clear();
}
There is no excellent answer to this question. But let me talk you through some concepts. Of course, there is no refresh, and the reason for this is many fold. Refresh might be added to the Frame someday, but it's problematic right now.
Consider a navigation service
A good way to navigate in your app is to offload this work to a NavigationService class. This is a simple class that has (something like) custom GotoAppHub() and GotoItemDetail(Item) methods.
The purpose of these methods is not because navigation is difficult, it is because navigation can be centralized. It can check & create the Frame; rather than leaving this erroneously in App.xaml.cs.
If your view model wants to navigate to a page, it simply calls NavigationService.GotoItemDetail(item); to do it, passing the item. This is smart for a few reasons, let me talk you through them.
The first reason this is smart is because you may not want to navigate at all. In some cases navigation relies on data being loaded or the user having permissions. Using the navigation service lets you centralize both the navigation logic and the tests necessary to validate the action.
The second reason this is smart is it allows you to retain the parameter passed to the navigation request. Remember that the Frame does NOT serialize custom, complex types. As a result, passing item in this case is a bad practice. The navigation service can persist this parameter somewhere so the target view model can come pick it up. Moreover, it can persist it for your Refresh().
Consider a static repository class
When a view model is loaded, it should be unnecessary for it to know what previous view model caused it to load. Instead the view model should know what it is supposed to do. And to do its work, it needs data. Every view model can use the repository class to ask for the "current" record. That current record will be set by the navigation service when navigation occurs. In addition, the repository class knows what to do when there is no current record, fetching it should it need.
In addition to holding a reference to the current record, the repository class also understands persistence. What I mean is, when the app is loaded, it knows how to fill the lists. When the app is suspended, it knows how to save the data to a file or web service, or whatever you use. The view model, as a result, does not know this and is, as a result, simpler and easier to maintain.
Consider the Reload() method
It is in the navigation service where you need the reload method. Even more than that, it is only in the navigation service where the reload method can be most effective since the navigation service knows the current type and the current parameter value. The navigation service can store these values in local fields and the reload method can simple repeat the navigation.
Remember the back stack, however. This is like a browser's navigation and repeating the navigation will mean that the same page will exist twice and the GoBack() method you also have in your navigation service will not go back until you go back twice. The solution is simple, just remember to remove with Services.NavigationService.Instance.Frame.BackStack.Remove().
Remember the cost of loading
Sometimes when a page loads there is a considerable cost in loading the UI. This is because whatever you are doing isn't trivial. Calling the Reload() will cause the load of the page to repeat. This is a cost you simply cannot overcome. But, there might be dependencies on the loading of the page that should be bypassed. For example, you might initiate a web service operation when the page is loaded - and that operation should not be repeated. This is up to you to retain a static Boolean that indicates the page has already loaded. But it's important you do not forget it.
One more benefit of the repository
A few paragraphs above I mentioned that your navigation service is the one that can remember the last passed parameter for the reload method to work. If you have an internal rule that only the navigation service can write to the concurrency class then your navigation service doesn't really have to remember. It just has to remember the last navigated-to type. That's because the concurrency class will already have the reference to the item passed in. This is, however, not always useful. Sometimes reload is called to throw away the current changes, which means the current item needs to be reloaded or current changes must be flushed. This will all have to be custom, but I would feel bad if I didn't at least mention it.
Conclusion
This should only be taken as a recommendation. Having said that, I have described here the bulk of large, successful WPF and Windows apps in the marketplace. Using the MVVP pattern, the service pattern for navigation, the repository pattern for concurrency - it's all pretty well proven. But you are the developer. In the end, you should choose what is best.
If you don't like any of that, you can do this:
public bool Reload()
{
if (!this.Frame.BackStack.Any())
return false;
var current = this.Frame.BackStack.First();
this.Frame.BackStack.Remove(current);
return this.Frame.Navigate(current.SourcePageType, current.Parameter);
}
Best of luck!
How about:
private string parameter;
protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
parameter = (string)navigationParameter;
reloadData();
}
private void reloadData()
{
var sampleDataGroups = SampleDataSource.GetGroups(parameter);
this.DefaultViewModel["Groups"] = sampleDataGroups;
}
private void refresh(object sender, RoutedEventArgs e)
{
reloadData()
}

How to overwrite the session property?

Question:
Normally, one accesses the session object like this:
Session["foo"] = "bar";
I have written a wrapper over it, which is generic, and which checks whether a session has expired or not, and throws a SessionExpiredException if that is so.
In order to use my session access, I have to access sessions over my class like this
WebApplications.SessionAccess.Set<string>("foo", "bar");
Now, obviously, despite the presence of the class SessionAccess, one could still access the session via the normal session object. This is not desirable, and additonally, I want to later include it in a larger old project which has been written using the normal Session, which would mean I would have to replace all calls to session (a number in the low thousands) with my wrapper.
Is there a way I can overwrite the System.Web.HttpSessionStateBase.Controller.Session - Property with my own ?
The thing is, without a custom session handler defined in web.config, because there sometimes already is one for using the database for sessions (one could still initialize a module in Global.asax).
Those NULL-Reference exception YSODs on SessionTimeout are hyper-disturbing.
If possible, a solution that works on classical ASP.NET web-forms as well as on MVC.
I don't think that there will be any full-proof solution as you wants it but few tricks can make your life easier.
Create yet another wrapper that provides indexer property so that you can easily substitute calls such as Session["key"] = "name" to your wrapper property;
You need to inherit all your pages (i.e. code-behind classes) from a common base page class (that itself has inherited indirectly from System.Web.UI.Page). If you already have such base page then you are really in good situation. Inherit your common page base class from an internal base class that itself inherited from System.Web.UI.Page.
In the common page base, add a new Session property that would return your wrapper object created in #1. Similar trick has to be done for UserControl (and custom control) if you have many of them. This will save you from replacing the most of Session["key"] = "name" kind of calls.
Finally, override Session property in the internal base page class to add a debug assertion. You may choose to return null but that would break production usage. Debug assertion is a lot better to find session usage that will be escaped from #3.
As said, this is not a full-proof solution as one can still access the session state via HttpContext. But it should make the migration of legacy code to your session accessor object easier.

.Net Application-wide variables

I'm fairly new to .Net... I have several queries which will execute when the application loads. I want these queries to store the data in an object (a dataset?) which is accessible throughout the application. Should I be using a singleton class? How can a User Control within my application reference public variables in the main application code?
I guess I haven't found a good resource on how / where to store application variables and how to reference them when I need to populate a ListBox, DataGridView, etc.
As a background I'm most familiar with developing using Flex Builder 3, sorry for the vague question... I'm having a problem locating a good reference on the topic (not just populating a Control, but storing the data at an application level and referencing it from anywhere within the app).
Edit: This is for programming a windows forms application using C#
Sounds like you're using ASP.NET, in which case Application State (MSDN) will allow you to store and retrieve application-wide data that can be accessed from anywhere in the application.
More here:
How to: Save Values in Application State
How to: Read Values from Application State
If you're writing a desktop app, you should create a static class that contains your application wide data, e.g:
public static class ApplicationSettings
{
public static string InstallDirectory { get { ... } set { ... } };
public static DataSet SomeDataSet { get { ... } set { ... } };
static ApplicationSettings()
{
// ... initialize or load settings here
}
}
A singleton isn't necessary here, but if you do require lazy initialization and thread satefy you might want to take that route.
You could store the information in a App.config file and use the AppSettingsReader class to access the data.
EDIT: Seeing that you don't want to query the information multiple times, you could use a Singleton to access and cache the data.
Presumably your objects will be required as long as the application's main form is open. If so, simply store them as properties of the form.
Singletons are bad, m'kay? ;)
Or, more to the point, global data (especially mutable global data) is generally not a good thing. It makes classes difficult to test and debug. Small scope is good scope.
One option is to look at an IoC Container library (aka a DI framework).
IoC = Inversion of Control
DI = Dependency Injection (or Inversion)
Basically you can set up constructors on your classes that need access to the global data and add a parameter of your "singleton" type - except it's not a singleton, just a Plain Old Object (or interface). Then you tell the Container that your "global data" class has a long lifespan, and use the Container to create your other objects. You won't use the "new" keyword much anymore. The benefit is that the Container will automagically wire everything up for you, creating one and only one instance of the global class and injecting it in to all of the other constructed objects.
Here's an (incomplete) list of the libraries/frameworks for .NET:
IoC Container Benchmark
Ninject's another one. I use Unity, but that doesn't mean it's the best for you.
Here's another list:
http://elegantcode.com/2009/01/07/ioc-libraries-compared/

What will be the way to go with classes in ASP.NET?

In my asp.net web app. I have three classes (inside app_code folder) under namespace WPP which are as follows:
1. wpp_Common
2. wpp_SQL
3. wpp_Admin
All these classes contains different functions which I am using in my application to accomplish different tasks. Such as, wpp_common contains a function which make my URL's SEO'd, and wpp_SQL have some functions which I am using to get details from database.
Now, I am using these classes on different web pages web pages and in web controls. To use these classes I am creating instances of all three classes on the page where I am using them.
protected WPP.wpp_Common ObjCommon = new WPP.wpp_Common();
protected WPP.wpp_SQL ObjSQL = new WPP.wpp_SQL();
protected WPP.wpp_Admin ObjAdmin = new WPP.wpp_Admin();
So, I want to know, is this a better and only way to access my classes by making seprate instances at every page, is this method have any performance constraints.
Or is there a better and logical way to access my classes from ASP.net web pages and web controls.
Thanks.
If these classes don't encapsulate anything mutable, it may be worth making the key methods utilized static. Then, you don't even need an instance of the class. This seems to make sense for your SEO class. The SQL class you may want a shared instance as it may contain a reference to some SQL connection/class, but this could also be a parameter in a static method.
What you're doing seems okay to me, though.
Really the answer boils down to the complexity of the class. If your classes are lightweight and have low initialization overhead, then you are probably OK with instatiating objects every time. (Heck, even the ASP.NET runtime creates a new instance of your page object every time in classic ASP.NET - not sure about MVC).
But if your object has non-trivial initialization time (intensive processing in constructor or upon first method call), then you'll probably want to look at two options:
One) Storing the object in the session - be careful here as your object may behave differently depending on the backend session store (memory, sql, etc).
MyHeavyObj obj = (MyHeaveyObj) Session["cachedObj"];
if (obj == null)
{
obj = new MyHeavyObj();
obj.Init();
Session["cachedObj"] = obj;
}
obj.DoSomething();
Two) Writing your own Windows Service that serves up your objects via remoting and takes care of initiatlization internally. The drawback here is you need to make sure your service scales as your traffic grows.
MyHeavyObj obj = GetHeavyObjViaRemoting();
obj.DoSomething();

Categories

Resources